Bug Summary

File:home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx
Warning:line 233, column 1
Potential leak of memory pointed to by field '_M_pi'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name slidefragmenthandler.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D OOX_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/oox/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/nss/dist/public/nss -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/nss/dist/out/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx

/home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <com/sun/star/beans/XPropertySet.hpp>
21#include <com/sun/star/container/XNamed.hpp>
22#include <com/sun/star/drawing/XDrawPage.hpp>
23#include <tools/diagnose_ex.h>
24
25#include <oox/helper/attributelist.hxx>
26#include <oox/helper/propertyset.hxx>
27#include <oox/core/xmlfilterbase.hxx>
28#include "headerfootercontext.hxx"
29#include <oox/ppt/backgroundproperties.hxx>
30#include <oox/ppt/slidefragmenthandler.hxx>
31#include <oox/ppt/slidetimingcontext.hxx>
32#include <oox/ppt/slidetransitioncontext.hxx>
33#include <oox/ppt/slidemastertextstylescontext.hxx>
34#include <oox/ppt/pptshapegroupcontext.hxx>
35#include <oox/ppt/pptshape.hxx>
36#include <oox/vml/vmldrawing.hxx>
37#include <oox/vml/vmldrawingfragment.hxx>
38#include <drawingml/clrschemecontext.hxx>
39#include <drawingml/fillproperties.hxx>
40#include <oox/ppt/pptimport.hxx>
41#include <oox/token/namespaces.hxx>
42#include <oox/token/properties.hxx>
43#include <oox/token/tokens.hxx>
44
45using namespace ::com::sun::star;
46using namespace ::oox::core;
47using namespace ::oox::drawingml;
48using namespace ::com::sun::star::uno;
49using namespace ::com::sun::star::drawing;
50using namespace ::com::sun::star::xml::sax;
51using namespace ::com::sun::star::container;
52
53namespace oox::ppt {
54
55SlideFragmentHandler::SlideFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, const SlidePersistPtr& pPersistPtr, const ShapeLocation eShapeLocation )
56: FragmentHandler2( rFilter, rFragmentPath )
57, mpSlidePersistPtr( pPersistPtr )
58, meShapeLocation( eShapeLocation )
59{
60 OUString aVMLDrawingFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( "vmlDrawing" );
61 if( !aVMLDrawingFragmentPath.isEmpty() )
62 getFilter().importFragment( new oox::vml::DrawingFragment(
63 getFilter(), aVMLDrawingFragmentPath, *pPersistPtr->getDrawing() ) );
64}
65
66SlideFragmentHandler::~SlideFragmentHandler()
67{
68 // convert and insert all VML shapes (mostly form controls)
69 mpSlidePersistPtr->getDrawing()->convertAndInsert();
70}
71
72::oox::core::ContextHandlerRef SlideFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
73{
74 switch( aElementToken )
1
Control jumps to 'case 2032860:' at line 179
75 {
76 case PPT_TOKEN( sldMaster )(::oox::NMSP_ppt | ::oox::XML_sldMaster): // CT_SlideMaster
77 case PPT_TOKEN( handoutMaster )(::oox::NMSP_ppt | ::oox::XML_handoutMaster): // CT_HandoutMaster
78 case PPT_TOKEN( sld )(::oox::NMSP_ppt | ::oox::XML_sld): // CT_CommonSlideData
79 {
80 Reference< XDrawPage > xSlide( mpSlidePersistPtr->getPage() );
81 PropertyMap aPropMap;
82 PropertySet aSlideProp( xSlide );
83
84 aPropMap.setProperty( PROP_Visible, rAttribs.getBool( XML_show, true ));
85 aSlideProp.setProperties( aPropMap );
86
87 return this;
88 }
89 case PPT_TOKEN( notes )(::oox::NMSP_ppt | ::oox::XML_notes): // CT_NotesSlide
90 {
91 // Import notesMaster
92 PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
93 OUString aNotesFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( "notesMaster" );
94
95 std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() );
96 bool bNotesFragmentPathFound = false;
97 for (auto const& masterPage : rMasterPages)
98 {
99 if( masterPage->getPath() == aNotesFragmentPath )
100 {
101 if( !mpSlidePersistPtr->getMasterPersist() )
102 mpSlidePersistPtr->setMasterPersist(masterPage);
103 bNotesFragmentPathFound=true;
104 break;
105 }
106 }
107 if( !bNotesFragmentPathFound && !mpSlidePersistPtr->getMasterPersist() )
108 {
109 SlidePersistPtr pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, true, mpSlidePersistPtr->getPage(),
110 std::make_shared<PPTShape>( Master, "com.sun.star.drawing.GroupShape" ), mpSlidePersistPtr->getNotesTextStyle() );
111 pMasterPersistPtr->setPath( aNotesFragmentPath );
112 rFilter.getMasterPages().push_back( pMasterPersistPtr );
113 FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, aNotesFragmentPath, pMasterPersistPtr, Master ) );
114 rFilter.importFragment( xMasterFragmentHandler );
115 mpSlidePersistPtr->setMasterPersist( pMasterPersistPtr );
116 }
117 return this;
118 }
119 case PPT_TOKEN( notesMaster )(::oox::NMSP_ppt | ::oox::XML_notesMaster): // CT_NotesMaster
120 return this;
121 case PPT_TOKEN( cSld )(::oox::NMSP_ppt | ::oox::XML_cSld): // CT_CommonSlideData
122 maSlideName = rAttribs.getString(XML_name, OUString());
123 return this;
124
125 case PPT_TOKEN( spTree )(::oox::NMSP_ppt | ::oox::XML_spTree): // CT_GroupShape
126 {
127 return new PPTShapeGroupContext(
128 *this, mpSlidePersistPtr, meShapeLocation, mpSlidePersistPtr->getShapes(),
129 std::make_shared<PPTShape>( meShapeLocation, "com.sun.star.drawing.GroupShape" ) );
130 }
131 break;
132
133 case PPT_TOKEN( controls )(::oox::NMSP_ppt | ::oox::XML_controls):
134 return this;
135 case PPT_TOKEN( control )(::oox::NMSP_ppt | ::oox::XML_control):
136 {
137 ::oox::vml::ControlInfo aInfo;
138 aInfo.setShapeId( rAttribs.getInteger( XML_spid, 0 ) );
139 aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id )(::oox::NMSP_officeRel | ::oox::XML_id), OUString() ) );
140 aInfo.maName = rAttribs.getXString( XML_name, OUString() );
141 mpSlidePersistPtr->getDrawing()->registerControl( aInfo );
142 }
143 return this;
144
145 case PPT_TOKEN( timing )(::oox::NMSP_ppt | ::oox::XML_timing): // CT_SlideTiming
146 return new SlideTimingContext( *this, mpSlidePersistPtr->getTimeNodeList() );
147 case PPT_TOKEN( transition )(::oox::NMSP_ppt | ::oox::XML_transition): // CT_SlideTransition
148 return new SlideTransitionContext( *this, rAttribs, maSlideProperties );
149 case PPT_TOKEN( hf )(::oox::NMSP_ppt | ::oox::XML_hf):
150 return new HeaderFooterContext( *this, rAttribs, mpSlidePersistPtr->getHeaderFooter() );
151
152 // BackgroundGroup
153 case PPT_TOKEN( bg )(::oox::NMSP_ppt | ::oox::XML_bg):
154 return this;
155 case PPT_TOKEN( bgPr )(::oox::NMSP_ppt | ::oox::XML_bgPr): // CT_BackgroundProperties
156 {
157 FillPropertiesPtr pFillPropertiesPtr =std::make_shared<FillProperties>();
158 mpSlidePersistPtr->setBackgroundProperties( pFillPropertiesPtr );
159 return new BackgroundPropertiesContext( *this, *pFillPropertiesPtr );
160 }
161 break;
162
163 case PPT_TOKEN( bgRef )(::oox::NMSP_ppt | ::oox::XML_bgRef): // a:CT_StyleMatrixReference
164 {
165 const FillProperties *pFillProperties = nullptr;
166 if( mpSlidePersistPtr->getTheme() )
167 pFillProperties = mpSlidePersistPtr->getTheme()->getFillStyle( rAttribs.getInteger( XML_idx, -1 ) );
168 FillPropertiesPtr pFillPropertiesPtr =
169 pFillProperties
170 ? std::make_shared<FillProperties>( *pFillProperties )
171 : std::make_shared<FillProperties>();
172 mpSlidePersistPtr->setBackgroundProperties( pFillPropertiesPtr );
173 ContextHandlerRef ret = new ColorContext( *this, mpSlidePersistPtr->getBackgroundColor() );
174 return ret;
175 }
176 break;
177
178 case A_TOKEN( overrideClrMapping )(::oox::NMSP_dml | ::oox::XML_overrideClrMapping):
179 case PPT_TOKEN( clrMap )(::oox::NMSP_ppt | ::oox::XML_clrMap): // CT_ColorMapping
180 {
181 oox::drawingml::ClrMapPtr pClrMapPtr =
182 ( aElementToken == PPT_TOKEN( clrMap )(::oox::NMSP_ppt | ::oox::XML_clrMap) || !mpSlidePersistPtr || !mpSlidePersistPtr->getClrMap() )
183 ? std::make_shared<oox::drawingml::ClrMap>()
2
Calling 'make_shared<oox::drawingml::ClrMap, >'
20
Returned allocated memory
184 : std::make_shared<oox::drawingml::ClrMap>( *mpSlidePersistPtr->getClrMap() );
185 ContextHandlerRef ret = new oox::drawingml::clrMapContext( *this, rAttribs, *pClrMapPtr );
186 mpSlidePersistPtr->setClrMap( pClrMapPtr );
187 return ret;
188 }
189 break;
190 case PPT_TOKEN( clrMapOvr )(::oox::NMSP_ppt | ::oox::XML_clrMapOvr): // CT_ColorMappingOverride
191 case PPT_TOKEN( sldLayoutIdLst )(::oox::NMSP_ppt | ::oox::XML_sldLayoutIdLst): // CT_SlideLayoutIdList
192 return this;
193 case PPT_TOKEN( txStyles )(::oox::NMSP_ppt | ::oox::XML_txStyles): // CT_SlideMasterTextStyles
194 return new SlideMasterTextStylesContext( *this, mpSlidePersistPtr );
195 case PPT_TOKEN( custDataLst )(::oox::NMSP_ppt | ::oox::XML_custDataLst): // CT_CustomerDataList
196 case PPT_TOKEN( tagLst )(::oox::NMSP_ppt | ::oox::XML_tagLst): // CT_TagList
197 return this;
198
199 //for Comments
200 case PPT_TOKEN( cmLst )(::oox::NMSP_ppt | ::oox::XML_cmLst):
201 break;
202 case PPT_TOKEN( cm )(::oox::NMSP_ppt | ::oox::XML_cm):
203 if (!mpSlidePersistPtr->getCommentsList().cmLst.empty() && !getCharVector().empty())
204 {
205 // set comment text for earlier comment
206 mpSlidePersistPtr->getCommentsList().cmLst.back().setText( getCharVector().back() );
207 }
208 // insert a new comment in vector commentsList
209 mpSlidePersistPtr->getCommentsList().cmLst.emplace_back();
210 mpSlidePersistPtr->getCommentsList().cmLst.back().setAuthorId(rAttribs.getString(XML_authorId, OUString()));
211 mpSlidePersistPtr->getCommentsList().cmLst.back().setdt(rAttribs.getString(XML_dt, OUString()));
212 mpSlidePersistPtr->getCommentsList().cmLst.back().setidx(rAttribs.getString(XML_idx, OUString()));
213 break;
214
215 case PPT_TOKEN( pos )(::oox::NMSP_ppt | ::oox::XML_pos):
216 mpSlidePersistPtr->getCommentsList().cmLst.back().setPoint(
217 rAttribs.getString(XML_x, OUString()),
218 rAttribs.getString(XML_y, OUString()));
219 break;
220
221 case PPT_TOKEN( cmAuthor )(::oox::NMSP_ppt | ::oox::XML_cmAuthor):
222 CommentAuthor _author;
223 _author.clrIdx = rAttribs.getString(XML_clrIdx, OUString());
224 _author.id = rAttribs.getString(XML_id, OUString());
225 _author.initials = rAttribs.getString(XML_initials, OUString());
226 _author.lastIdx = rAttribs.getString(XML_lastIdx, OUString());
227 _author.name = rAttribs.getString(XML_name, OUString());
228 mpSlidePersistPtr->getCommentAuthors().addAuthor(_author);
229 break;
230 }
231
232 return this;
233}
21
Potential leak of memory pointed to by field '_M_pi'
234void SlideFragmentHandler::onCharacters( const OUString& rChars)
235{
236 maCharVector.push_back(rChars);
237}
238void SlideFragmentHandler::finalizeImport()
239{
240 try
241 {
242 Reference< XDrawPage > xSlide( mpSlidePersistPtr->getPage() );
243 PropertySet aSlideProp( xSlide );
244 aSlideProp.setProperties( maSlideProperties );
245 if ( !maSlideName.isEmpty() )
246 {
247 Reference< XNamed > xNamed( xSlide, UNO_QUERY );
248 if( xNamed.is() )
249 xNamed->setName( maSlideName );
250 }
251 }
252 catch( uno::Exception& )
253 {
254 TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::SlideFragmentHandler::EndElement()" )do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "oox")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "oox::ppt::SlideFragmentHandler::EndElement()" <<
" " << exceptionToString(tools_warn_exception)) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("oox"), ("/home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx"
":" "254" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "oox::ppt::SlideFragmentHandler::EndElement()"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "oox::ppt::SlideFragmentHandler::EndElement()" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("oox"), ("/home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx"
":" "254" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "oox::ppt::SlideFragmentHandler::EndElement()" <<
" " << exceptionToString(tools_warn_exception)) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("oox"), ("/home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx"
":" "254" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "oox::ppt::SlideFragmentHandler::EndElement()"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "oox::ppt::SlideFragmentHandler::EndElement()" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("oox"), ("/home/maarten/src/libreoffice/core/oox/source/ppt/slidefragmenthandler.cxx"
":" "254" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
255 }
256}
257
258}
259
260/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/shared_ptr.h

1// shared_ptr and weak_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2007-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_H1
50#define _SHARED_PTR_H1 1
51
52#include <bits/shared_ptr_base.h>
53
54namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup pointer_abstractions
60 * @{
61 */
62
63 // 20.7.2.2.11 shared_ptr I/O
64
65 /// Write the stored pointer to an ostream.
66 /// @relates shared_ptr
67 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
68 inline std::basic_ostream<_Ch, _Tr>&
69 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
70 const __shared_ptr<_Tp, _Lp>& __p)
71 {
72 __os << __p.get();
73 return __os;
74 }
75
76 template<typename _Del, typename _Tp, _Lock_policy _Lp>
77 inline _Del*
78 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
79 {
80#if __cpp_rtti199711L
81 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
82#else
83 return 0;
84#endif
85 }
86
87 /// 20.7.2.2.10 shared_ptr get_deleter
88
89 /// If `__p` has a deleter of type `_Del`, return a pointer to it.
90 /// @relates shared_ptr
91 template<typename _Del, typename _Tp>
92 inline _Del*
93 get_deleter(const shared_ptr<_Tp>& __p) noexcept
94 {
95#if __cpp_rtti199711L
96 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
97#else
98 return 0;
99#endif
100 }
101
102 /**
103 * @brief A smart pointer with reference-counted copy semantics.
104 *
105 * A `shared_ptr` object is either empty or _owns_ a pointer passed
106 * to the constructor. Copies of a `shared_ptr` share ownership of
107 * the same pointer. When the last `shared_ptr` that owns the pointer
108 * is destroyed or reset, the owned pointer is freed (either by `delete`
109 * or by invoking a custom deleter that was passed to the constructor).
110 *
111 * A `shared_ptr` also stores another pointer, which is usually
112 * (but not always) the same pointer as it owns. The stored pointer
113 * can be retrieved by calling the `get()` member function.
114 *
115 * The equality and relational operators for `shared_ptr` only compare
116 * the stored pointer returned by `get()`, not the owned pointer.
117 * To test whether two `shared_ptr` objects share ownership of the same
118 * pointer see `std::shared_ptr::owner_before` and `std::owner_less`.
119 */
120 template<typename _Tp>
121 class shared_ptr : public __shared_ptr<_Tp>
122 {
123 template<typename... _Args>
124 using _Constructible = typename enable_if<
125 is_constructible<__shared_ptr<_Tp>, _Args...>::value
126 >::type;
127
128 template<typename _Arg>
129 using _Assignable = typename enable_if<
130 is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
131 >::type;
132
133 public:
134
135 /// The type pointed to by the stored pointer, remove_extent_t<_Tp>
136 using element_type = typename __shared_ptr<_Tp>::element_type;
137
138#if __cplusplus201703L >= 201703L
139# define __cpp_lib_shared_ptr_weak_type201606 201606
140 /// The corresponding weak_ptr type for this shared_ptr
141 using weak_type = weak_ptr<_Tp>;
142#endif
143 /**
144 * @brief Construct an empty %shared_ptr.
145 * @post use_count()==0 && get()==0
146 */
147 constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
148
149 shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
150
151 /**
152 * @brief Construct a %shared_ptr that owns the pointer @a __p.
153 * @param __p A pointer that is convertible to element_type*.
154 * @post use_count() == 1 && get() == __p
155 * @throw std::bad_alloc, in which case @c delete @a __p is called.
156 */
157 template<typename _Yp, typename = _Constructible<_Yp*>>
158 explicit
159 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
160
161 /**
162 * @brief Construct a %shared_ptr that owns the pointer @a __p
163 * and the deleter @a __d.
164 * @param __p A pointer.
165 * @param __d A deleter.
166 * @post use_count() == 1 && get() == __p
167 * @throw std::bad_alloc, in which case @a __d(__p) is called.
168 *
169 * Requirements: _Deleter's copy constructor and destructor must
170 * not throw
171 *
172 * __shared_ptr will release __p by calling __d(__p)
173 */
174 template<typename _Yp, typename _Deleter,
175 typename = _Constructible<_Yp*, _Deleter>>
176 shared_ptr(_Yp* __p, _Deleter __d)
177 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
178
179 /**
180 * @brief Construct a %shared_ptr that owns a null pointer
181 * and the deleter @a __d.
182 * @param __p A null pointer constant.
183 * @param __d A deleter.
184 * @post use_count() == 1 && get() == __p
185 * @throw std::bad_alloc, in which case @a __d(__p) is called.
186 *
187 * Requirements: _Deleter's copy constructor and destructor must
188 * not throw
189 *
190 * The last owner will call __d(__p)
191 */
192 template<typename _Deleter>
193 shared_ptr(nullptr_t __p, _Deleter __d)
194 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
195
196 /**
197 * @brief Construct a %shared_ptr that owns the pointer @a __p
198 * and the deleter @a __d.
199 * @param __p A pointer.
200 * @param __d A deleter.
201 * @param __a An allocator.
202 * @post use_count() == 1 && get() == __p
203 * @throw std::bad_alloc, in which case @a __d(__p) is called.
204 *
205 * Requirements: _Deleter's copy constructor and destructor must
206 * not throw _Alloc's copy constructor and destructor must not
207 * throw.
208 *
209 * __shared_ptr will release __p by calling __d(__p)
210 */
211 template<typename _Yp, typename _Deleter, typename _Alloc,
212 typename = _Constructible<_Yp*, _Deleter, _Alloc>>
213 shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
214 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
215
216 /**
217 * @brief Construct a %shared_ptr that owns a null pointer
218 * and the deleter @a __d.
219 * @param __p A null pointer constant.
220 * @param __d A deleter.
221 * @param __a An allocator.
222 * @post use_count() == 1 && get() == __p
223 * @throw std::bad_alloc, in which case @a __d(__p) is called.
224 *
225 * Requirements: _Deleter's copy constructor and destructor must
226 * not throw _Alloc's copy constructor and destructor must not
227 * throw.
228 *
229 * The last owner will call __d(__p)
230 */
231 template<typename _Deleter, typename _Alloc>
232 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
233 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
234
235 // Aliasing constructor
236
237 /**
238 * @brief Constructs a `shared_ptr` instance that stores `__p`
239 * and shares ownership with `__r`.
240 * @param __r A `shared_ptr`.
241 * @param __p A pointer that will remain valid while `*__r` is valid.
242 * @post `get() == __p && use_count() == __r.use_count()`
243 *
244 * This can be used to construct a `shared_ptr` to a sub-object
245 * of an object managed by an existing `shared_ptr`. The complete
246 * object will remain valid while any `shared_ptr` owns it, even
247 * if they don't store a pointer to the complete object.
248 *
249 * @code
250 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
251 * shared_ptr<int> pi(pii, &pii->first);
252 * assert(pii.use_count() == 2);
253 * @endcode
254 */
255 template<typename _Yp>
256 shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
257 : __shared_ptr<_Tp>(__r, __p) { }
258
259#if __cplusplus201703L > 201703L
260 // _GLIBCXX_RESOLVE_LIB_DEFECTS
261 // 2996. Missing rvalue overloads for shared_ptr operations
262 /**
263 * @brief Constructs a `shared_ptr` instance that stores `__p`
264 * and shares ownership with `__r`.
265 * @param __r A `shared_ptr`.
266 * @param __p A pointer that will remain valid while `*__r` is valid.
267 * @post `get() == __p && !__r.use_count() && !__r.get()`
268 *
269 * This can be used to construct a `shared_ptr` to a sub-object
270 * of an object managed by an existing `shared_ptr`. The complete
271 * object will remain valid while any `shared_ptr` owns it, even
272 * if they don't store a pointer to the complete object.
273 *
274 * @code
275 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
276 * shared_ptr<int> pi1(pii, &pii->first);
277 * assert(pii.use_count() == 2);
278 * shared_ptr<int> pi2(std::move(pii), &pii->second);
279 * assert(pii.use_count() == 0);
280 * @endcode
281 */
282 template<typename _Yp>
283 shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
284 : __shared_ptr<_Tp>(std::move(__r), __p) { }
285#endif
286 /**
287 * @brief If @a __r is empty, constructs an empty %shared_ptr;
288 * otherwise construct a %shared_ptr that shares ownership
289 * with @a __r.
290 * @param __r A %shared_ptr.
291 * @post get() == __r.get() && use_count() == __r.use_count()
292 */
293 template<typename _Yp,
294 typename = _Constructible<const shared_ptr<_Yp>&>>
295 shared_ptr(const shared_ptr<_Yp>& __r) noexcept
296 : __shared_ptr<_Tp>(__r) { }
297
298 /**
299 * @brief Move-constructs a %shared_ptr instance from @a __r.
300 * @param __r A %shared_ptr rvalue.
301 * @post *this contains the old value of @a __r, @a __r is empty.
302 */
303 shared_ptr(shared_ptr&& __r) noexcept
304 : __shared_ptr<_Tp>(std::move(__r)) { }
305
306 /**
307 * @brief Move-constructs a %shared_ptr instance from @a __r.
308 * @param __r A %shared_ptr rvalue.
309 * @post *this contains the old value of @a __r, @a __r is empty.
310 */
311 template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
312 shared_ptr(shared_ptr<_Yp>&& __r) noexcept
313 : __shared_ptr<_Tp>(std::move(__r)) { }
314
315 /**
316 * @brief Constructs a %shared_ptr that shares ownership with @a __r
317 * and stores a copy of the pointer stored in @a __r.
318 * @param __r A weak_ptr.
319 * @post use_count() == __r.use_count()
320 * @throw bad_weak_ptr when __r.expired(),
321 * in which case the constructor has no effect.
322 */
323 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
324 explicit shared_ptr(const weak_ptr<_Yp>& __r)
325 : __shared_ptr<_Tp>(__r) { }
326
327#if _GLIBCXX_USE_DEPRECATED1
328#pragma GCC diagnostic push
329#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
330 template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
331 shared_ptr(auto_ptr<_Yp>&& __r);
332#pragma GCC diagnostic pop
333#endif
334
335 // _GLIBCXX_RESOLVE_LIB_DEFECTS
336 // 2399. shared_ptr's constructor from unique_ptr should be constrained
337 template<typename _Yp, typename _Del,
338 typename = _Constructible<unique_ptr<_Yp, _Del>>>
339 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
340 : __shared_ptr<_Tp>(std::move(__r)) { }
341
342#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
343 // This non-standard constructor exists to support conversions that
344 // were possible in C++11 and C++14 but are ill-formed in C++17.
345 // If an exception is thrown this constructor has no effect.
346 template<typename _Yp, typename _Del,
347 _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
348 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
349 : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
350#endif
351
352 /**
353 * @brief Construct an empty %shared_ptr.
354 * @post use_count() == 0 && get() == nullptr
355 */
356 constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
357
358 shared_ptr& operator=(const shared_ptr&) noexcept = default;
359
360 template<typename _Yp>
361 _Assignable<const shared_ptr<_Yp>&>
362 operator=(const shared_ptr<_Yp>& __r) noexcept
363 {
364 this->__shared_ptr<_Tp>::operator=(__r);
365 return *this;
366 }
367
368#if _GLIBCXX_USE_DEPRECATED1
369#pragma GCC diagnostic push
370#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
371 template<typename _Yp>
372 _Assignable<auto_ptr<_Yp>>
373 operator=(auto_ptr<_Yp>&& __r)
374 {
375 this->__shared_ptr<_Tp>::operator=(std::move(__r));
376 return *this;
377 }
378#pragma GCC diagnostic pop
379#endif
380
381 shared_ptr&
382 operator=(shared_ptr&& __r) noexcept
383 {
384 this->__shared_ptr<_Tp>::operator=(std::move(__r));
385 return *this;
386 }
387
388 template<class _Yp>
389 _Assignable<shared_ptr<_Yp>>
390 operator=(shared_ptr<_Yp>&& __r) noexcept
391 {
392 this->__shared_ptr<_Tp>::operator=(std::move(__r));
393 return *this;
394 }
395
396 template<typename _Yp, typename _Del>
397 _Assignable<unique_ptr<_Yp, _Del>>
398 operator=(unique_ptr<_Yp, _Del>&& __r)
399 {
400 this->__shared_ptr<_Tp>::operator=(std::move(__r));
401 return *this;
402 }
403
404 private:
405 // This constructor is non-standard, it is used by allocate_shared.
406 template<typename _Alloc, typename... _Args>
407 shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
408 : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
5
Calling constructor for '__shared_ptr<oox::drawingml::ClrMap, __gnu_cxx::_S_atomic>'
17
Returning from constructor for '__shared_ptr<oox::drawingml::ClrMap, __gnu_cxx::_S_atomic>'
409 { }
410
411 template<typename _Yp, typename _Alloc, typename... _Args>
412 friend shared_ptr<_Yp>
413 allocate_shared(const _Alloc& __a, _Args&&... __args);
414
415 // This constructor is non-standard, it is used by weak_ptr::lock().
416 shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
417 : __shared_ptr<_Tp>(__r, std::nothrow) { }
418
419 friend class weak_ptr<_Tp>;
420 };
421
422#if __cpp_deduction_guides201703L >= 201606
423 template<typename _Tp>
424 shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
425 template<typename _Tp, typename _Del>
426 shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
427#endif
428
429 // 20.7.2.2.7 shared_ptr comparisons
430
431 /// @relates shared_ptr @{
432
433 /// Equality operator for shared_ptr objects, compares the stored pointers
434 template<typename _Tp, typename _Up>
435 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
436 operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
437 { return __a.get() == __b.get(); }
438
439 /// shared_ptr comparison with nullptr
440 template<typename _Tp>
441 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
442 operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
443 { return !__a; }
444
445#ifdef __cpp_lib_three_way_comparison
446 template<typename _Tp, typename _Up>
447 inline strong_ordering
448 operator<=>(const shared_ptr<_Tp>& __a,
449 const shared_ptr<_Up>& __b) noexcept
450 { return compare_three_way()(__a.get(), __b.get()); }
451
452 template<typename _Tp>
453 inline strong_ordering
454 operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
455 {
456 using pointer = typename shared_ptr<_Tp>::element_type*;
457 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
458 }
459#else
460 /// shared_ptr comparison with nullptr
461 template<typename _Tp>
462 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
463 operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
464 { return !__a; }
465
466 /// Inequality operator for shared_ptr objects, compares the stored pointers
467 template<typename _Tp, typename _Up>
468 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
469 operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
470 { return __a.get() != __b.get(); }
471
472 /// shared_ptr comparison with nullptr
473 template<typename _Tp>
474 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
475 operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
476 { return (bool)__a; }
477
478 /// shared_ptr comparison with nullptr
479 template<typename _Tp>
480 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
481 operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
482 { return (bool)__a; }
483
484 /// Relational operator for shared_ptr objects, compares the stored pointers
485 template<typename _Tp, typename _Up>
486 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
487 operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
488 {
489 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
490 using _Up_elt = typename shared_ptr<_Up>::element_type;
491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
492 return less<_Vp>()(__a.get(), __b.get());
493 }
494
495 /// shared_ptr comparison with nullptr
496 template<typename _Tp>
497 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
498 operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
499 {
500 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
501 return less<_Tp_elt*>()(__a.get(), nullptr);
502 }
503
504 /// shared_ptr comparison with nullptr
505 template<typename _Tp>
506 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
507 operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
508 {
509 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
510 return less<_Tp_elt*>()(nullptr, __a.get());
511 }
512
513 /// Relational operator for shared_ptr objects, compares the stored pointers
514 template<typename _Tp, typename _Up>
515 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
516 operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
517 { return !(__b < __a); }
518
519 /// shared_ptr comparison with nullptr
520 template<typename _Tp>
521 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
522 operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
523 { return !(nullptr < __a); }
524
525 /// shared_ptr comparison with nullptr
526 template<typename _Tp>
527 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
528 operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
529 { return !(__a < nullptr); }
530
531 /// Relational operator for shared_ptr objects, compares the stored pointers
532 template<typename _Tp, typename _Up>
533 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
534 operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
535 { return (__b < __a); }
536
537 /// shared_ptr comparison with nullptr
538 template<typename _Tp>
539 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
540 operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
541 { return nullptr < __a; }
542
543 /// shared_ptr comparison with nullptr
544 template<typename _Tp>
545 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
546 operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
547 { return __a < nullptr; }
548
549 /// Relational operator for shared_ptr objects, compares the stored pointers
550 template<typename _Tp, typename _Up>
551 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
552 operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
553 { return !(__a < __b); }
554
555 /// shared_ptr comparison with nullptr
556 template<typename _Tp>
557 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
558 operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
559 { return !(__a < nullptr); }
560
561 /// shared_ptr comparison with nullptr
562 template<typename _Tp>
563 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
564 operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
565 { return !(nullptr < __a); }
566#endif
567
568 // 20.7.2.2.8 shared_ptr specialized algorithms.
569
570 /// Swap overload for shared_ptr
571 template<typename _Tp>
572 inline void
573 swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
574 { __a.swap(__b); }
575
576 // 20.7.2.2.9 shared_ptr casts.
577
578 /// Convert type of `shared_ptr`, via `static_cast`
579 template<typename _Tp, typename _Up>
580 inline shared_ptr<_Tp>
581 static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
582 {
583 using _Sp = shared_ptr<_Tp>;
584 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
585 }
586
587 /// Convert type of `shared_ptr`, via `const_cast`
588 template<typename _Tp, typename _Up>
589 inline shared_ptr<_Tp>
590 const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
591 {
592 using _Sp = shared_ptr<_Tp>;
593 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
594 }
595
596 /// Convert type of `shared_ptr`, via `dynamic_cast`
597 template<typename _Tp, typename _Up>
598 inline shared_ptr<_Tp>
599 dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
600 {
601 using _Sp = shared_ptr<_Tp>;
602 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
603 return _Sp(__r, __p);
604 return _Sp();
605 }
606
607#if __cplusplus201703L >= 201703L
608 /// Convert type of `shared_ptr`, via `reinterpret_cast`
609 template<typename _Tp, typename _Up>
610 inline shared_ptr<_Tp>
611 reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
612 {
613 using _Sp = shared_ptr<_Tp>;
614 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
615 }
616
617#if __cplusplus201703L > 201703L
618 // _GLIBCXX_RESOLVE_LIB_DEFECTS
619 // 2996. Missing rvalue overloads for shared_ptr operations
620
621 /// Convert type of `shared_ptr` rvalue, via `static_cast`
622 template<typename _Tp, typename _Up>
623 inline shared_ptr<_Tp>
624 static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
625 {
626 using _Sp = shared_ptr<_Tp>;
627 return _Sp(std::move(__r),
628 static_cast<typename _Sp::element_type*>(__r.get()));
629 }
630
631 /// Convert type of `shared_ptr` rvalue, via `const_cast`
632 template<typename _Tp, typename _Up>
633 inline shared_ptr<_Tp>
634 const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
635 {
636 using _Sp = shared_ptr<_Tp>;
637 return _Sp(std::move(__r),
638 const_cast<typename _Sp::element_type*>(__r.get()));
639 }
640
641 /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
642 template<typename _Tp, typename _Up>
643 inline shared_ptr<_Tp>
644 dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
645 {
646 using _Sp = shared_ptr<_Tp>;
647 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
648 return _Sp(std::move(__r), __p);
649 return _Sp();
650 }
651
652 /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
653 template<typename _Tp, typename _Up>
654 inline shared_ptr<_Tp>
655 reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
656 {
657 using _Sp = shared_ptr<_Tp>;
658 return _Sp(std::move(__r),
659 reinterpret_cast<typename _Sp::element_type*>(__r.get()));
660 }
661#endif // C++20
662#endif // C++17
663
664 // @}
665
666 /**
667 * @brief A non-owning observer for a pointer owned by a shared_ptr
668 *
669 * A weak_ptr provides a safe alternative to a raw pointer when you want
670 * a non-owning reference to an object that is managed by a shared_ptr.
671 *
672 * Unlike a raw pointer, a weak_ptr can be converted to a new shared_ptr
673 * that shares ownership with every other shared_ptr that already owns
674 * the pointer. In other words you can upgrade from a non-owning "weak"
675 * reference to an owning shared_ptr, without having access to any of
676 * the existing shared_ptr objects.
677 *
678 * Also unlike a raw pointer, a weak_ptr does not become "dangling" after
679 * the object it points to has been destroyed. Instead, a weak_ptr
680 * becomes _expired_ and can no longer be converted to a shared_ptr that
681 * owns the freed pointer, so you cannot accidentally access the pointed-to
682 * object after it has been destroyed.
683 */
684 template<typename _Tp>
685 class weak_ptr : public __weak_ptr<_Tp>
686 {
687 template<typename _Arg>
688 using _Constructible = typename enable_if<
689 is_constructible<__weak_ptr<_Tp>, _Arg>::value
690 >::type;
691
692 template<typename _Arg>
693 using _Assignable = typename enable_if<
694 is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
695 >::type;
696
697 public:
698 constexpr weak_ptr() noexcept = default;
699
700 template<typename _Yp,
701 typename = _Constructible<const shared_ptr<_Yp>&>>
702 weak_ptr(const shared_ptr<_Yp>& __r) noexcept
703 : __weak_ptr<_Tp>(__r) { }
704
705 weak_ptr(const weak_ptr&) noexcept = default;
706
707 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
708 weak_ptr(const weak_ptr<_Yp>& __r) noexcept
709 : __weak_ptr<_Tp>(__r) { }
710
711 weak_ptr(weak_ptr&&) noexcept = default;
712
713 template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
714 weak_ptr(weak_ptr<_Yp>&& __r) noexcept
715 : __weak_ptr<_Tp>(std::move(__r)) { }
716
717 weak_ptr&
718 operator=(const weak_ptr& __r) noexcept = default;
719
720 template<typename _Yp>
721 _Assignable<const weak_ptr<_Yp>&>
722 operator=(const weak_ptr<_Yp>& __r) noexcept
723 {
724 this->__weak_ptr<_Tp>::operator=(__r);
725 return *this;
726 }
727
728 template<typename _Yp>
729 _Assignable<const shared_ptr<_Yp>&>
730 operator=(const shared_ptr<_Yp>& __r) noexcept
731 {
732 this->__weak_ptr<_Tp>::operator=(__r);
733 return *this;
734 }
735
736 weak_ptr&
737 operator=(weak_ptr&& __r) noexcept = default;
738
739 template<typename _Yp>
740 _Assignable<weak_ptr<_Yp>>
741 operator=(weak_ptr<_Yp>&& __r) noexcept
742 {
743 this->__weak_ptr<_Tp>::operator=(std::move(__r));
744 return *this;
745 }
746
747 shared_ptr<_Tp>
748 lock() const noexcept
749 { return shared_ptr<_Tp>(*this, std::nothrow); }
750 };
751
752#if __cpp_deduction_guides201703L >= 201606
753 template<typename _Tp>
754 weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
755#endif
756
757 // 20.7.2.3.6 weak_ptr specialized algorithms.
758 /// Swap overload for weak_ptr
759 /// @relates weak_ptr
760 template<typename _Tp>
761 inline void
762 swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
763 { __a.swap(__b); }
764
765
766 /// Primary template owner_less
767 template<typename _Tp = void>
768 struct owner_less;
769
770 /// Void specialization of owner_less compares either shared_ptr or weak_ptr
771 template<>
772 struct owner_less<void> : _Sp_owner_less<void, void>
773 { };
774
775 /// Partial specialization of owner_less for shared_ptr.
776 template<typename _Tp>
777 struct owner_less<shared_ptr<_Tp>>
778 : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
779 { };
780
781 /// Partial specialization of owner_less for weak_ptr.
782 template<typename _Tp>
783 struct owner_less<weak_ptr<_Tp>>
784 : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
785 { };
786
787 /**
788 * @brief Base class allowing use of member function shared_from_this.
789 */
790 template<typename _Tp>
791 class enable_shared_from_this
792 {
793 protected:
794 constexpr enable_shared_from_this() noexcept { }
795
796 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
797
798 enable_shared_from_this&
799 operator=(const enable_shared_from_this&) noexcept
800 { return *this; }
801
802 ~enable_shared_from_this() { }
803
804 public:
805 shared_ptr<_Tp>
806 shared_from_this()
807 { return shared_ptr<_Tp>(this->_M_weak_this); }
808
809 shared_ptr<const _Tp>
810 shared_from_this() const
811 { return shared_ptr<const _Tp>(this->_M_weak_this); }
812
813#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
814#define __cpp_lib_enable_shared_from_this201603 201603
815 weak_ptr<_Tp>
816 weak_from_this() noexcept
817 { return this->_M_weak_this; }
818
819 weak_ptr<const _Tp>
820 weak_from_this() const noexcept
821 { return this->_M_weak_this; }
822#endif
823
824 private:
825 template<typename _Tp1>
826 void
827 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
828 { _M_weak_this._M_assign(__p, __n); }
829
830 // Found by ADL when this is an associated class.
831 friend const enable_shared_from_this*
832 __enable_shared_from_this_base(const __shared_count<>&,
833 const enable_shared_from_this* __p)
834 { return __p; }
835
836 template<typename, _Lock_policy>
837 friend class __shared_ptr;
838
839 mutable weak_ptr<_Tp> _M_weak_this;
840 };
841
842 /// @relates shared_ptr @{
843
844 /**
845 * @brief Create an object that is owned by a shared_ptr.
846 * @param __a An allocator.
847 * @param __args Arguments for the @a _Tp object's constructor.
848 * @return A shared_ptr that owns the newly created object.
849 * @throw An exception thrown from @a _Alloc::allocate or from the
850 * constructor of @a _Tp.
851 *
852 * A copy of @a __a will be used to allocate memory for the shared_ptr
853 * and the new object.
854 */
855 template<typename _Tp, typename _Alloc, typename... _Args>
856 inline shared_ptr<_Tp>
857 allocate_shared(const _Alloc& __a, _Args&&... __args)
858 {
859 return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
4
Calling constructor for 'shared_ptr<oox::drawingml::ClrMap>'
18
Returning from constructor for 'shared_ptr<oox::drawingml::ClrMap>'
860 std::forward<_Args>(__args)...);
861 }
862
863 /**
864 * @brief Create an object that is owned by a shared_ptr.
865 * @param __args Arguments for the @a _Tp object's constructor.
866 * @return A shared_ptr that owns the newly created object.
867 * @throw std::bad_alloc, or an exception thrown from the
868 * constructor of @a _Tp.
869 */
870 template<typename _Tp, typename... _Args>
871 inline shared_ptr<_Tp>
872 make_shared(_Args&&... __args)
873 {
874 typedef typename std::remove_cv<_Tp>::type _Tp_nc;
875 return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
3
Calling 'allocate_shared<oox::drawingml::ClrMap, std::allocator<oox::drawingml::ClrMap>, >'
19
Returned allocated memory
876 std::forward<_Args>(__args)...);
877 }
878
879 /// std::hash specialization for shared_ptr.
880 template<typename _Tp>
881 struct hash<shared_ptr<_Tp>>
882 : public __hash_base<size_t, shared_ptr<_Tp>>
883 {
884 size_t
885 operator()(const shared_ptr<_Tp>& __s) const noexcept
886 {
887 return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
888 }
889 };
890
891 // @} relates shared_ptr
892 // @} group pointer_abstractions
893
894#if __cplusplus201703L >= 201703L
895 namespace __detail::__variant
896 {
897 template<typename> struct _Never_valueless_alt; // see <variant>
898
899 // Provide the strong exception-safety guarantee when emplacing a
900 // shared_ptr into a variant.
901 template<typename _Tp>
902 struct _Never_valueless_alt<std::shared_ptr<_Tp>>
903 : std::true_type
904 { };
905
906 // Provide the strong exception-safety guarantee when emplacing a
907 // weak_ptr into a variant.
908 template<typename _Tp>
909 struct _Never_valueless_alt<std::weak_ptr<_Tp>>
910 : std::true_type
911 { };
912 } // namespace __detail::__variant
913#endif // C++17
914
915_GLIBCXX_END_NAMESPACE_VERSION
916} // namespace
917
918#endif // _SHARED_PTR_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/shared_ptr_base.h

1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H1
50#define _SHARED_PTR_BASE_H1 1
51
52#include <typeinfo>
53#include <bits/allocated_ptr.h>
54#include <bits/refwrap.h>
55#include <bits/stl_function.h>
56#include <ext/aligned_buffer.h>
57#if __cplusplus201703L > 201703L
58# include <compare>
59#endif
60
61namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
62{
63_GLIBCXX_BEGIN_NAMESPACE_VERSION
64
65#if _GLIBCXX_USE_DEPRECATED1
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
68 template<typename> class auto_ptr;
69#pragma GCC diagnostic pop
70#endif
71
72 /**
73 * @brief Exception possibly thrown by @c shared_ptr.
74 * @ingroup exceptions
75 */
76 class bad_weak_ptr : public std::exception
77 {
78 public:
79 virtual char const* what() const noexcept;
80
81 virtual ~bad_weak_ptr() noexcept;
82 };
83
84 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
85 inline void
86 __throw_bad_weak_ptr()
87 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr())(throw (bad_weak_ptr())); }
88
89 using __gnu_cxx::_Lock_policy;
90 using __gnu_cxx::__default_lock_policy;
91 using __gnu_cxx::_S_single;
92 using __gnu_cxx::_S_mutex;
93 using __gnu_cxx::_S_atomic;
94
95 // Empty helper class except when the template argument is _S_mutex.
96 template<_Lock_policy _Lp>
97 class _Mutex_base
98 {
99 protected:
100 // The atomic policy uses fully-fenced builtins, single doesn't care.
101 enum { _S_need_barriers = 0 };
102 };
103
104 template<>
105 class _Mutex_base<_S_mutex>
106 : public __gnu_cxx::__mutex
107 {
108 protected:
109 // This policy is used when atomic builtins are not available.
110 // The replacement atomic operations might not have the necessary
111 // memory barriers.
112 enum { _S_need_barriers = 1 };
113 };
114
115 template<_Lock_policy _Lp = __default_lock_policy>
116 class _Sp_counted_base
117 : public _Mutex_base<_Lp>
118 {
119 public:
120 _Sp_counted_base() noexcept
121 : _M_use_count(1), _M_weak_count(1) { }
122
123 virtual
124 ~_Sp_counted_base() noexcept
125 { }
126
127 // Called when _M_use_count drops to zero, to release the resources
128 // managed by *this.
129 virtual void
130 _M_dispose() noexcept = 0;
131
132 // Called when _M_weak_count drops to zero.
133 virtual void
134 _M_destroy() noexcept
135 { delete this; }
136
137 virtual void*
138 _M_get_deleter(const std::type_info&) noexcept = 0;
139
140 void
141 _M_add_ref_copy()
142 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
143
144 void
145 _M_add_ref_lock();
146
147 bool
148 _M_add_ref_lock_nothrow();
149
150 void
151 _M_release() noexcept
152 {
153 // Be race-detector-friendly. For more info see bits/c++config.
154 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
155 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
156 {
157 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
158 _M_dispose();
159 // There must be a memory barrier between dispose() and destroy()
160 // to ensure that the effects of dispose() are observed in the
161 // thread that runs destroy().
162 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
163 if (_Mutex_base<_Lp>::_S_need_barriers)
164 {
165 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
166 }
167
168 // Be race-detector-friendly. For more info see bits/c++config.
169 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
170 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
171 -1) == 1)
172 {
173 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
174 _M_destroy();
175 }
176 }
177 }
178
179 void
180 _M_weak_add_ref() noexcept
181 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
182
183 void
184 _M_weak_release() noexcept
185 {
186 // Be race-detector-friendly. For more info see bits/c++config.
187 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
188 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
189 {
190 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
191 if (_Mutex_base<_Lp>::_S_need_barriers)
192 {
193 // See _M_release(),
194 // destroy() must observe results of dispose()
195 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
196 }
197 _M_destroy();
198 }
199 }
200
201 long
202 _M_get_use_count() const noexcept
203 {
204 // No memory barrier is used here so there is no synchronization
205 // with other threads.
206 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED0);
207 }
208
209 private:
210 _Sp_counted_base(_Sp_counted_base const&) = delete;
211 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
212
213 _Atomic_word _M_use_count; // #shared
214 _Atomic_word _M_weak_count; // #weak + (#shared != 0)
215 };
216
217 template<>
218 inline void
219 _Sp_counted_base<_S_single>::
220 _M_add_ref_lock()
221 {
222 if (_M_use_count == 0)
223 __throw_bad_weak_ptr();
224 ++_M_use_count;
225 }
226
227 template<>
228 inline void
229 _Sp_counted_base<_S_mutex>::
230 _M_add_ref_lock()
231 {
232 __gnu_cxx::__scoped_lock sentry(*this);
233 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
234 {
235 _M_use_count = 0;
236 __throw_bad_weak_ptr();
237 }
238 }
239
240 template<>
241 inline void
242 _Sp_counted_base<_S_atomic>::
243 _M_add_ref_lock()
244 {
245 // Perform lock-free add-if-not-zero operation.
246 _Atomic_word __count = _M_get_use_count();
247 do
248 {
249 if (__count == 0)
250 __throw_bad_weak_ptr();
251 // Replace the current counter value with the old value + 1, as
252 // long as it's not changed meanwhile.
253 }
254 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
255 true, __ATOMIC_ACQ_REL4,
256 __ATOMIC_RELAXED0));
257 }
258
259 template<>
260 inline bool
261 _Sp_counted_base<_S_single>::
262 _M_add_ref_lock_nothrow()
263 {
264 if (_M_use_count == 0)
265 return false;
266 ++_M_use_count;
267 return true;
268 }
269
270 template<>
271 inline bool
272 _Sp_counted_base<_S_mutex>::
273 _M_add_ref_lock_nothrow()
274 {
275 __gnu_cxx::__scoped_lock sentry(*this);
276 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
277 {
278 _M_use_count = 0;
279 return false;
280 }
281 return true;
282 }
283
284 template<>
285 inline bool
286 _Sp_counted_base<_S_atomic>::
287 _M_add_ref_lock_nothrow()
288 {
289 // Perform lock-free add-if-not-zero operation.
290 _Atomic_word __count = _M_get_use_count();
291 do
292 {
293 if (__count == 0)
294 return false;
295 // Replace the current counter value with the old value + 1, as
296 // long as it's not changed meanwhile.
297 }
298 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
299 true, __ATOMIC_ACQ_REL4,
300 __ATOMIC_RELAXED0));
301 return true;
302 }
303
304 template<>
305 inline void
306 _Sp_counted_base<_S_single>::_M_add_ref_copy()
307 { ++_M_use_count; }
308
309 template<>
310 inline void
311 _Sp_counted_base<_S_single>::_M_release() noexcept
312 {
313 if (--_M_use_count == 0)
314 {
315 _M_dispose();
316 if (--_M_weak_count == 0)
317 _M_destroy();
318 }
319 }
320
321 template<>
322 inline void
323 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
324 { ++_M_weak_count; }
325
326 template<>
327 inline void
328 _Sp_counted_base<_S_single>::_M_weak_release() noexcept
329 {
330 if (--_M_weak_count == 0)
331 _M_destroy();
332 }
333
334 template<>
335 inline long
336 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
337 { return _M_use_count; }
338
339
340 // Forward declarations.
341 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
342 class __shared_ptr;
343
344 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
345 class __weak_ptr;
346
347 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
348 class __enable_shared_from_this;
349
350 template<typename _Tp>
351 class shared_ptr;
352
353 template<typename _Tp>
354 class weak_ptr;
355
356 template<typename _Tp>
357 struct owner_less;
358
359 template<typename _Tp>
360 class enable_shared_from_this;
361
362 template<_Lock_policy _Lp = __default_lock_policy>
363 class __weak_count;
364
365 template<_Lock_policy _Lp = __default_lock_policy>
366 class __shared_count;
367
368
369 // Counted ptr with no deleter or allocator support
370 template<typename _Ptr, _Lock_policy _Lp>
371 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
372 {
373 public:
374 explicit
375 _Sp_counted_ptr(_Ptr __p) noexcept
376 : _M_ptr(__p) { }
377
378 virtual void
379 _M_dispose() noexcept
380 { delete _M_ptr; }
381
382 virtual void
383 _M_destroy() noexcept
384 { delete this; }
385
386 virtual void*
387 _M_get_deleter(const std::type_info&) noexcept
388 { return nullptr; }
389
390 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
391 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
392
393 private:
394 _Ptr _M_ptr;
395 };
396
397 template<>
398 inline void
399 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
400
401 template<>
402 inline void
403 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
404
405 template<>
406 inline void
407 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
408
409 template<int _Nm, typename _Tp,
410 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
411 struct _Sp_ebo_helper;
412
413 /// Specialization using EBO.
414 template<int _Nm, typename _Tp>
415 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
416 {
417 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
418 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
419
420 static _Tp&
421 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
422 };
423
424 /// Specialization not using EBO.
425 template<int _Nm, typename _Tp>
426 struct _Sp_ebo_helper<_Nm, _Tp, false>
427 {
428 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
429 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
430
431 static _Tp&
432 _S_get(_Sp_ebo_helper& __eboh)
433 { return __eboh._M_tp; }
434
435 private:
436 _Tp _M_tp;
437 };
438
439 // Support for custom deleter and/or allocator
440 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
441 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
442 {
443 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
444 {
445 typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
446 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
447
448 public:
449 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
450 : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
451 { }
452
453 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
454 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
455
456 _Ptr _M_ptr;
457 };
458
459 public:
460 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
461
462 // __d(__p) must not throw.
463 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
464 : _M_impl(__p, std::move(__d), _Alloc()) { }
465
466 // __d(__p) must not throw.
467 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
468 : _M_impl(__p, std::move(__d), __a) { }
469
470 ~_Sp_counted_deleter() noexcept { }
471
472 virtual void
473 _M_dispose() noexcept
474 { _M_impl._M_del()(_M_impl._M_ptr); }
475
476 virtual void
477 _M_destroy() noexcept
478 {
479 __allocator_type __a(_M_impl._M_alloc());
480 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
481 this->~_Sp_counted_deleter();
482 }
483
484 virtual void*
485 _M_get_deleter(const std::type_info& __ti) noexcept
486 {
487#if __cpp_rtti199711L
488 // _GLIBCXX_RESOLVE_LIB_DEFECTS
489 // 2400. shared_ptr's get_deleter() should use addressof()
490 return __ti == typeid(_Deleter)
491 ? std::__addressof(_M_impl._M_del())
492 : nullptr;
493#else
494 return nullptr;
495#endif
496 }
497
498 private:
499 _Impl _M_impl;
500 };
501
502 // helpers for make_shared / allocate_shared
503
504 struct _Sp_make_shared_tag
505 {
506 private:
507 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
508 friend class _Sp_counted_ptr_inplace;
509
510 static const type_info&
511 _S_ti() noexcept _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
512 {
513 alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
514 return reinterpret_cast<const type_info&>(__tag);
515 }
516
517 static bool _S_eq(const type_info&) noexcept;
518 };
519
520 template<typename _Alloc>
521 struct _Sp_alloc_shared_tag
522 {
523 const _Alloc& _M_a;
524 };
525
526 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
527 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
528 {
529 class _Impl : _Sp_ebo_helper<0, _Alloc>
530 {
531 typedef _Sp_ebo_helper<0, _Alloc> _A_base;
532
533 public:
534 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
535
536 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
537
538 __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
539 };
540
541 public:
542 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
543
544 // Alloc parameter is not a reference so doesn't alias anything in __args
545 template<typename... _Args>
546 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
547 : _M_impl(__a)
548 {
549 // _GLIBCXX_RESOLVE_LIB_DEFECTS
550 // 2070. allocate_shared should use allocator_traits<A>::construct
551 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
552 std::forward<_Args>(__args)...); // might throw
553 }
554
555 ~_Sp_counted_ptr_inplace() noexcept { }
556
557 virtual void
558 _M_dispose() noexcept
559 {
560 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
561 }
562
563 // Override because the allocator needs to know the dynamic type
564 virtual void
565 _M_destroy() noexcept
566 {
567 __allocator_type __a(_M_impl._M_alloc());
568 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
569 this->~_Sp_counted_ptr_inplace();
570 }
571
572 private:
573 friend class __shared_count<_Lp>; // To be able to call _M_ptr().
574
575 // No longer used, but code compiled against old libstdc++ headers
576 // might still call it from __shared_ptr ctor to get the pointer out.
577 virtual void*
578 _M_get_deleter(const std::type_info& __ti) noexcept override
579 {
580 auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
581 // Check for the fake type_info first, so we don't try to access it
582 // as a real type_info object. Otherwise, check if it's the real
583 // type_info for this class. With RTTI enabled we can check directly,
584 // or call a library function to do it.
585 if (&__ti == &_Sp_make_shared_tag::_S_ti()
586 ||
587#if __cpp_rtti199711L
588 __ti == typeid(_Sp_make_shared_tag)
589#else
590 _Sp_make_shared_tag::_S_eq(__ti)
591#endif
592 )
593 return __ptr;
594 return nullptr;
595 }
596
597 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
598
599 _Impl _M_impl;
600 };
601
602 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
603 struct __sp_array_delete
604 {
605 template<typename _Yp>
606 void operator()(_Yp* __p) const { delete[] __p; }
607 };
608
609 template<_Lock_policy _Lp>
610 class __shared_count
611 {
612 template<typename _Tp>
613 struct __not_alloc_shared_tag { using type = void; };
614
615 template<typename _Tp>
616 struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
617
618 public:
619 constexpr __shared_count() noexcept : _M_pi(0)
620 { }
621
622 template<typename _Ptr>
623 explicit
624 __shared_count(_Ptr __p) : _M_pi(0)
625 {
626 __trytry
627 {
628 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
629 }
630 __catch(...)catch(...)
631 {
632 delete __p;
633 __throw_exception_againthrow;
634 }
635 }
636
637 template<typename _Ptr>
638 __shared_count(_Ptr __p, /* is_array = */ false_type)
639 : __shared_count(__p)
640 { }
641
642 template<typename _Ptr>
643 __shared_count(_Ptr __p, /* is_array = */ true_type)
644 : __shared_count(__p, __sp_array_delete{}, allocator<void>())
645 { }
646
647 template<typename _Ptr, typename _Deleter,
648 typename = typename __not_alloc_shared_tag<_Deleter>::type>
649 __shared_count(_Ptr __p, _Deleter __d)
650 : __shared_count(__p, std::move(__d), allocator<void>())
651 { }
652
653 template<typename _Ptr, typename _Deleter, typename _Alloc,
654 typename = typename __not_alloc_shared_tag<_Deleter>::type>
655 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
656 {
657 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
658 __trytry
659 {
660 typename _Sp_cd_type::__allocator_type __a2(__a);
661 auto __guard = std::__allocate_guarded(__a2);
662 _Sp_cd_type* __mem = __guard.get();
663 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
664 _M_pi = __mem;
665 __guard = nullptr;
666 }
667 __catch(...)catch(...)
668 {
669 __d(__p); // Call _Deleter on __p.
670 __throw_exception_againthrow;
671 }
672 }
673
674 template<typename _Tp, typename _Alloc, typename... _Args>
675 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
676 _Args&&... __args)
677 {
678 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
679 typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
680 auto __guard = std::__allocate_guarded(__a2);
7
Calling '__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<oox::drawingml::ClrMap, std::allocator<oox::drawingml::ClrMap>, __gnu_cxx::_S_atomic>>>'
15
Returned allocated memory
681 _Sp_cp_type* __mem = __guard.get();
682 auto __pi = ::new (__mem)
683 _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
684 __guard = nullptr;
685 _M_pi = __pi;
686 __p = __pi->_M_ptr();
687 }
688
689#if _GLIBCXX_USE_DEPRECATED1
690#pragma GCC diagnostic push
691#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
692 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
693 template<typename _Tp>
694 explicit
695 __shared_count(std::auto_ptr<_Tp>&& __r);
696#pragma GCC diagnostic pop
697#endif
698
699 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
700 template<typename _Tp, typename _Del>
701 explicit
702 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
703 {
704 // _GLIBCXX_RESOLVE_LIB_DEFECTS
705 // 2415. Inconsistency between unique_ptr and shared_ptr
706 if (__r.get() == nullptr)
707 return;
708
709 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
710 using _Del2 = typename conditional<is_reference<_Del>::value,
711 reference_wrapper<typename remove_reference<_Del>::type>,
712 _Del>::type;
713 using _Sp_cd_type
714 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
715 using _Alloc = allocator<_Sp_cd_type>;
716 using _Alloc_traits = allocator_traits<_Alloc>;
717 _Alloc __a;
718 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
719 _Alloc_traits::construct(__a, __mem, __r.release(),
720 __r.get_deleter()); // non-throwing
721 _M_pi = __mem;
722 }
723
724 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
725 explicit __shared_count(const __weak_count<_Lp>& __r);
726
727 // Does not throw if __r._M_get_use_count() == 0, caller must check.
728 explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
729
730 ~__shared_count() noexcept
731 {
732 if (_M_pi != nullptr)
733 _M_pi->_M_release();
734 }
735
736 __shared_count(const __shared_count& __r) noexcept
737 : _M_pi(__r._M_pi)
738 {
739 if (_M_pi != 0)
740 _M_pi->_M_add_ref_copy();
741 }
742
743 __shared_count&
744 operator=(const __shared_count& __r) noexcept
745 {
746 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
747 if (__tmp != _M_pi)
748 {
749 if (__tmp != 0)
750 __tmp->_M_add_ref_copy();
751 if (_M_pi != 0)
752 _M_pi->_M_release();
753 _M_pi = __tmp;
754 }
755 return *this;
756 }
757
758 void
759 _M_swap(__shared_count& __r) noexcept
760 {
761 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
762 __r._M_pi = _M_pi;
763 _M_pi = __tmp;
764 }
765
766 long
767 _M_get_use_count() const noexcept
768 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
769
770 bool
771 _M_unique() const noexcept
772 { return this->_M_get_use_count() == 1; }
773
774 void*
775 _M_get_deleter(const std::type_info& __ti) const noexcept
776 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
777
778 bool
779 _M_less(const __shared_count& __rhs) const noexcept
780 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
781
782 bool
783 _M_less(const __weak_count<_Lp>& __rhs) const noexcept
784 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
785
786 // Friend function injected into enclosing namespace and found by ADL
787 friend inline bool
788 operator==(const __shared_count& __a, const __shared_count& __b) noexcept
789 { return __a._M_pi == __b._M_pi; }
790
791 private:
792 friend class __weak_count<_Lp>;
793
794 _Sp_counted_base<_Lp>* _M_pi;
795 };
796
797
798 template<_Lock_policy _Lp>
799 class __weak_count
800 {
801 public:
802 constexpr __weak_count() noexcept : _M_pi(nullptr)
803 { }
804
805 __weak_count(const __shared_count<_Lp>& __r) noexcept
806 : _M_pi(__r._M_pi)
807 {
808 if (_M_pi != nullptr)
809 _M_pi->_M_weak_add_ref();
810 }
811
812 __weak_count(const __weak_count& __r) noexcept
813 : _M_pi(__r._M_pi)
814 {
815 if (_M_pi != nullptr)
816 _M_pi->_M_weak_add_ref();
817 }
818
819 __weak_count(__weak_count&& __r) noexcept
820 : _M_pi(__r._M_pi)
821 { __r._M_pi = nullptr; }
822
823 ~__weak_count() noexcept
824 {
825 if (_M_pi != nullptr)
826 _M_pi->_M_weak_release();
827 }
828
829 __weak_count&
830 operator=(const __shared_count<_Lp>& __r) noexcept
831 {
832 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
833 if (__tmp != nullptr)
834 __tmp->_M_weak_add_ref();
835 if (_M_pi != nullptr)
836 _M_pi->_M_weak_release();
837 _M_pi = __tmp;
838 return *this;
839 }
840
841 __weak_count&
842 operator=(const __weak_count& __r) noexcept
843 {
844 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
845 if (__tmp != nullptr)
846 __tmp->_M_weak_add_ref();
847 if (_M_pi != nullptr)
848 _M_pi->_M_weak_release();
849 _M_pi = __tmp;
850 return *this;
851 }
852
853 __weak_count&
854 operator=(__weak_count&& __r) noexcept
855 {
856 if (_M_pi != nullptr)
857 _M_pi->_M_weak_release();
858 _M_pi = __r._M_pi;
859 __r._M_pi = nullptr;
860 return *this;
861 }
862
863 void
864 _M_swap(__weak_count& __r) noexcept
865 {
866 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
867 __r._M_pi = _M_pi;
868 _M_pi = __tmp;
869 }
870
871 long
872 _M_get_use_count() const noexcept
873 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
874
875 bool
876 _M_less(const __weak_count& __rhs) const noexcept
877 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
878
879 bool
880 _M_less(const __shared_count<_Lp>& __rhs) const noexcept
881 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
882
883 // Friend function injected into enclosing namespace and found by ADL
884 friend inline bool
885 operator==(const __weak_count& __a, const __weak_count& __b) noexcept
886 { return __a._M_pi == __b._M_pi; }
887
888 private:
889 friend class __shared_count<_Lp>;
890
891 _Sp_counted_base<_Lp>* _M_pi;
892 };
893
894 // Now that __weak_count is defined we can define this constructor:
895 template<_Lock_policy _Lp>
896 inline
897 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
898 : _M_pi(__r._M_pi)
899 {
900 if (_M_pi != nullptr)
901 _M_pi->_M_add_ref_lock();
902 else
903 __throw_bad_weak_ptr();
904 }
905
906 // Now that __weak_count is defined we can define this constructor:
907 template<_Lock_policy _Lp>
908 inline
909 __shared_count<_Lp>::
910 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
911 : _M_pi(__r._M_pi)
912 {
913 if (_M_pi != nullptr)
914 if (!_M_pi->_M_add_ref_lock_nothrow())
915 _M_pi = nullptr;
916 }
917
918#define __cpp_lib_shared_ptr_arrays201611L 201611L
919
920 // Helper traits for shared_ptr of array:
921
922 // A pointer type Y* is said to be compatible with a pointer type T* when
923 // either Y* is convertible to T* or Y is U[N] and T is U cv [].
924 template<typename _Yp_ptr, typename _Tp_ptr>
925 struct __sp_compatible_with
926 : false_type
927 { };
928
929 template<typename _Yp, typename _Tp>
930 struct __sp_compatible_with<_Yp*, _Tp*>
931 : is_convertible<_Yp*, _Tp*>::type
932 { };
933
934 template<typename _Up, size_t _Nm>
935 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
936 : true_type
937 { };
938
939 template<typename _Up, size_t _Nm>
940 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
941 : true_type
942 { };
943
944 template<typename _Up, size_t _Nm>
945 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
946 : true_type
947 { };
948
949 template<typename _Up, size_t _Nm>
950 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
951 : true_type
952 { };
953
954 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
955 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
956 struct __sp_is_constructible_arrN
957 : false_type
958 { };
959
960 template<typename _Up, size_t _Nm, typename _Yp>
961 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
962 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
963 { };
964
965 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
966 template<typename _Up, typename _Yp, typename = void>
967 struct __sp_is_constructible_arr
968 : false_type
969 { };
970
971 template<typename _Up, typename _Yp>
972 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
973 : is_convertible<_Yp(*)[], _Up(*)[]>::type
974 { };
975
976 // Trait to check if shared_ptr<T> can be constructed from Y*.
977 template<typename _Tp, typename _Yp>
978 struct __sp_is_constructible;
979
980 // When T is U[N], Y(*)[N] shall be convertible to T*;
981 template<typename _Up, size_t _Nm, typename _Yp>
982 struct __sp_is_constructible<_Up[_Nm], _Yp>
983 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
984 { };
985
986 // when T is U[], Y(*)[] shall be convertible to T*;
987 template<typename _Up, typename _Yp>
988 struct __sp_is_constructible<_Up[], _Yp>
989 : __sp_is_constructible_arr<_Up, _Yp>::type
990 { };
991
992 // otherwise, Y* shall be convertible to T*.
993 template<typename _Tp, typename _Yp>
994 struct __sp_is_constructible
995 : is_convertible<_Yp*, _Tp*>::type
996 { };
997
998
999 // Define operator* and operator-> for shared_ptr<T>.
1000 template<typename _Tp, _Lock_policy _Lp,
1001 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
1002 class __shared_ptr_access
1003 {
1004 public:
1005 using element_type = _Tp;
1006
1007 element_type&
1008 operator*() const noexcept
1009 {
1010 __glibcxx_assert(_M_get() != nullptr);
1011 return *_M_get();
1012 }
1013
1014 element_type*
1015 operator->() const noexcept
1016 {
1017 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1018 return _M_get();
1019 }
1020
1021 private:
1022 element_type*
1023 _M_get() const noexcept
1024 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1025 };
1026
1027 // Define operator-> for shared_ptr<cv void>.
1028 template<typename _Tp, _Lock_policy _Lp>
1029 class __shared_ptr_access<_Tp, _Lp, false, true>
1030 {
1031 public:
1032 using element_type = _Tp;
1033
1034 element_type*
1035 operator->() const noexcept
1036 {
1037 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
1038 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
1039 return __ptr;
1040 }
1041 };
1042
1043 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
1044 template<typename _Tp, _Lock_policy _Lp>
1045 class __shared_ptr_access<_Tp, _Lp, true, false>
1046 {
1047 public:
1048 using element_type = typename remove_extent<_Tp>::type;
1049
1050#if __cplusplus201703L <= 201402L
1051 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
1052 element_type&
1053 operator*() const noexcept
1054 {
1055 __glibcxx_assert(_M_get() != nullptr);
1056 return *_M_get();
1057 }
1058
1059 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
1060 element_type*
1061 operator->() const noexcept
1062 {
1063 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1064 return _M_get();
1065 }
1066#endif
1067
1068 element_type&
1069 operator[](ptrdiff_t __i) const
1070 {
1071 __glibcxx_assert(_M_get() != nullptr);
1072 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
1073 return _M_get()[__i];
1074 }
1075
1076 private:
1077 element_type*
1078 _M_get() const noexcept
1079 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1080 };
1081
1082 template<typename _Tp, _Lock_policy _Lp>
1083 class __shared_ptr
1084 : public __shared_ptr_access<_Tp, _Lp>
1085 {
1086 public:
1087 using element_type = typename remove_extent<_Tp>::type;
1088
1089 private:
1090 // Constraint for taking ownership of a pointer of type _Yp*:
1091 template<typename _Yp>
1092 using _SafeConv
1093 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
1094
1095 // Constraint for construction from shared_ptr and weak_ptr:
1096 template<typename _Yp, typename _Res = void>
1097 using _Compatible = typename
1098 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1099
1100 // Constraint for assignment from shared_ptr and weak_ptr:
1101 template<typename _Yp>
1102 using _Assignable = _Compatible<_Yp, __shared_ptr&>;
1103
1104 // Constraint for construction from unique_ptr:
1105 template<typename _Yp, typename _Del, typename _Res = void,
1106 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
1107 using _UniqCompatible = typename enable_if<__and_<
1108 __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>
1109 >::value, _Res>::type;
1110
1111 // Constraint for assignment from unique_ptr:
1112 template<typename _Yp, typename _Del>
1113 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
1114
1115 public:
1116
1117#if __cplusplus201703L > 201402L
1118 using weak_type = __weak_ptr<_Tp, _Lp>;
1119#endif
1120
1121 constexpr __shared_ptr() noexcept
1122 : _M_ptr(0), _M_refcount()
1123 { }
1124
1125 template<typename _Yp, typename = _SafeConv<_Yp>>
1126 explicit
1127 __shared_ptr(_Yp* __p)
1128 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
1129 {
1130 static_assert( !is_void<_Yp>::value, "incomplete type" );
1131 static_assert( sizeof(_Yp) > 0, "incomplete type" );
1132 _M_enable_shared_from_this_with(__p);
1133 }
1134
1135 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
1136 __shared_ptr(_Yp* __p, _Deleter __d)
1137 : _M_ptr(__p), _M_refcount(__p, std::move(__d))
1138 {
1139 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1140 "deleter expression d(p) is well-formed");
1141 _M_enable_shared_from_this_with(__p);
1142 }
1143
1144 template<typename _Yp, typename _Deleter, typename _Alloc,
1145 typename = _SafeConv<_Yp>>
1146 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
1147 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
1148 {
1149 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1150 "deleter expression d(p) is well-formed");
1151 _M_enable_shared_from_this_with(__p);
1152 }
1153
1154 template<typename _Deleter>
1155 __shared_ptr(nullptr_t __p, _Deleter __d)
1156 : _M_ptr(0), _M_refcount(__p, std::move(__d))
1157 { }
1158
1159 template<typename _Deleter, typename _Alloc>
1160 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
1161 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
1162 { }
1163
1164 // Aliasing constructor
1165 template<typename _Yp>
1166 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
1167 element_type* __p) noexcept
1168 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
1169 { }
1170
1171 // Aliasing constructor
1172 template<typename _Yp>
1173 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
1174 element_type* __p) noexcept
1175 : _M_ptr(__p), _M_refcount()
1176 {
1177 _M_refcount._M_swap(__r._M_refcount);
1178 __r._M_ptr = 0;
1179 }
1180
1181 __shared_ptr(const __shared_ptr&) noexcept = default;
1182 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
1183 ~__shared_ptr() = default;
1184
1185 template<typename _Yp, typename = _Compatible<_Yp>>
1186 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1187 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1188 { }
1189
1190 __shared_ptr(__shared_ptr&& __r) noexcept
1191 : _M_ptr(__r._M_ptr), _M_refcount()
1192 {
1193 _M_refcount._M_swap(__r._M_refcount);
1194 __r._M_ptr = 0;
1195 }
1196
1197 template<typename _Yp, typename = _Compatible<_Yp>>
1198 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1199 : _M_ptr(__r._M_ptr), _M_refcount()
1200 {
1201 _M_refcount._M_swap(__r._M_refcount);
1202 __r._M_ptr = 0;
1203 }
1204
1205 template<typename _Yp, typename = _Compatible<_Yp>>
1206 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
1207 : _M_refcount(__r._M_refcount) // may throw
1208 {
1209 // It is now safe to copy __r._M_ptr, as
1210 // _M_refcount(__r._M_refcount) did not throw.
1211 _M_ptr = __r._M_ptr;
1212 }
1213
1214 // If an exception is thrown this constructor has no effect.
1215 template<typename _Yp, typename _Del,
1216 typename = _UniqCompatible<_Yp, _Del>>
1217 __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
1218 : _M_ptr(__r.get()), _M_refcount()
1219 {
1220 auto __raw = __to_address(__r.get());
1221 _M_refcount = __shared_count<_Lp>(std::move(__r));
1222 _M_enable_shared_from_this_with(__raw);
1223 }
1224
1225#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
1226 protected:
1227 // If an exception is thrown this constructor has no effect.
1228 template<typename _Tp1, typename _Del,
1229 typename enable_if<__and_<
1230 __not_<is_array<_Tp>>, is_array<_Tp1>,
1231 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
1232 >::value, bool>::type = true>
1233 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
1234 : _M_ptr(__r.get()), _M_refcount()
1235 {
1236 auto __raw = __to_address(__r.get());
1237 _M_refcount = __shared_count<_Lp>(std::move(__r));
1238 _M_enable_shared_from_this_with(__raw);
1239 }
1240 public:
1241#endif
1242
1243#if _GLIBCXX_USE_DEPRECATED1
1244#pragma GCC diagnostic push
1245#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1246 // Postcondition: use_count() == 1 and __r.get() == 0
1247 template<typename _Yp, typename = _Compatible<_Yp>>
1248 __shared_ptr(auto_ptr<_Yp>&& __r);
1249#pragma GCC diagnostic pop
1250#endif
1251
1252 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
1253
1254 template<typename _Yp>
1255 _Assignable<_Yp>
1256 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1257 {
1258 _M_ptr = __r._M_ptr;
1259 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
1260 return *this;
1261 }
1262
1263#if _GLIBCXX_USE_DEPRECATED1
1264#pragma GCC diagnostic push
1265#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1266 template<typename _Yp>
1267 _Assignable<_Yp>
1268 operator=(auto_ptr<_Yp>&& __r)
1269 {
1270 __shared_ptr(std::move(__r)).swap(*this);
1271 return *this;
1272 }
1273#pragma GCC diagnostic pop
1274#endif
1275
1276 __shared_ptr&
1277 operator=(__shared_ptr&& __r) noexcept
1278 {
1279 __shared_ptr(std::move(__r)).swap(*this);
1280 return *this;
1281 }
1282
1283 template<class _Yp>
1284 _Assignable<_Yp>
1285 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1286 {
1287 __shared_ptr(std::move(__r)).swap(*this);
1288 return *this;
1289 }
1290
1291 template<typename _Yp, typename _Del>
1292 _UniqAssignable<_Yp, _Del>
1293 operator=(unique_ptr<_Yp, _Del>&& __r)
1294 {
1295 __shared_ptr(std::move(__r)).swap(*this);
1296 return *this;
1297 }
1298
1299 void
1300 reset() noexcept
1301 { __shared_ptr().swap(*this); }
1302
1303 template<typename _Yp>
1304 _SafeConv<_Yp>
1305 reset(_Yp* __p) // _Yp must be complete.
1306 {
1307 // Catch self-reset errors.
1308 __glibcxx_assert(__p == 0 || __p != _M_ptr);
1309 __shared_ptr(__p).swap(*this);
1310 }
1311
1312 template<typename _Yp, typename _Deleter>
1313 _SafeConv<_Yp>
1314 reset(_Yp* __p, _Deleter __d)
1315 { __shared_ptr(__p, std::move(__d)).swap(*this); }
1316
1317 template<typename _Yp, typename _Deleter, typename _Alloc>
1318 _SafeConv<_Yp>
1319 reset(_Yp* __p, _Deleter __d, _Alloc __a)
1320 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
1321
1322 /// Return the stored pointer.
1323 element_type*
1324 get() const noexcept
1325 { return _M_ptr; }
1326
1327 /// Return true if the stored pointer is not null.
1328 explicit operator bool() const // never throws
1329 { return _M_ptr == 0 ? false : true; }
1330
1331 /// Return true if use_count() == 1.
1332 bool
1333 unique() const noexcept
1334 { return _M_refcount._M_unique(); }
1335
1336 /// If *this owns a pointer, return the number of owners, otherwise zero.
1337 long
1338 use_count() const noexcept
1339 { return _M_refcount._M_get_use_count(); }
1340
1341 /// Exchange both the owned pointer and the stored pointer.
1342 void
1343 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
1344 {
1345 std::swap(_M_ptr, __other._M_ptr);
1346 _M_refcount._M_swap(__other._M_refcount);
1347 }
1348
1349 /** @brief Define an ordering based on ownership.
1350 *
1351 * This function defines a strict weak ordering between two shared_ptr
1352 * or weak_ptr objects, such that one object is less than the other
1353 * unless they share ownership of the same pointer, or are both empty.
1354 * @{
1355 */
1356 template<typename _Tp1>
1357 bool
1358 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1359 { return _M_refcount._M_less(__rhs._M_refcount); }
1360
1361 template<typename _Tp1>
1362 bool
1363 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1364 { return _M_refcount._M_less(__rhs._M_refcount); }
1365 // @}
1366
1367 protected:
1368 // This constructor is non-standard, it is used by allocate_shared.
1369 template<typename _Alloc, typename... _Args>
1370 __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
1371 : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
6
Calling constructor for '__shared_count<__gnu_cxx::_S_atomic>'
16
Returning from constructor for '__shared_count<__gnu_cxx::_S_atomic>'
1372 { _M_enable_shared_from_this_with(_M_ptr); }
1373
1374 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1375 typename... _Args>
1376 friend __shared_ptr<_Tp1, _Lp1>
1377 __allocate_shared(const _Alloc& __a, _Args&&... __args);
1378
1379 // This constructor is used by __weak_ptr::lock() and
1380 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
1381 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
1382 : _M_refcount(__r._M_refcount, std::nothrow)
1383 {
1384 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
1385 }
1386
1387 friend class __weak_ptr<_Tp, _Lp>;
1388
1389 private:
1390
1391 template<typename _Yp>
1392 using __esft_base_t = decltype(__enable_shared_from_this_base(
1393 std::declval<const __shared_count<_Lp>&>(),
1394 std::declval<_Yp*>()));
1395
1396 // Detect an accessible and unambiguous enable_shared_from_this base.
1397 template<typename _Yp, typename = void>
1398 struct __has_esft_base
1399 : false_type { };
1400
1401 template<typename _Yp>
1402 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
1403 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
1404
1405 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1406 typename enable_if<__has_esft_base<_Yp2>::value>::type
1407 _M_enable_shared_from_this_with(_Yp* __p) noexcept
1408 {
1409 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
1410 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
1411 }
1412
1413 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1414 typename enable_if<!__has_esft_base<_Yp2>::value>::type
1415 _M_enable_shared_from_this_with(_Yp*) noexcept
1416 { }
1417
1418 void*
1419 _M_get_deleter(const std::type_info& __ti) const noexcept
1420 { return _M_refcount._M_get_deleter(__ti); }
1421
1422 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1423 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1424
1425 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1426 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1427
1428 template<typename _Del, typename _Tp1>
1429 friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;
1430
1431 element_type* _M_ptr; // Contained pointer.
1432 __shared_count<_Lp> _M_refcount; // Reference counter.
1433 };
1434
1435
1436 // 20.7.2.2.7 shared_ptr comparisons
1437 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1438 inline bool
1439 operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1440 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1441 { return __a.get() == __b.get(); }
1442
1443 template<typename _Tp, _Lock_policy _Lp>
1444 inline bool
1445 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1446 { return !__a; }
1447
1448#ifdef __cpp_lib_three_way_comparison
1449 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1450 inline strong_ordering
1451 operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
1452 const __shared_ptr<_Up, _Lp>& __b) noexcept
1453 { return compare_three_way()(__a.get(), __b.get()); }
1454
1455 template<typename _Tp, _Lock_policy _Lp>
1456 inline strong_ordering
1457 operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1458 {
1459 using pointer = typename __shared_ptr<_Tp, _Lp>::element_type*;
1460 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
1461 }
1462#else
1463 template<typename _Tp, _Lock_policy _Lp>
1464 inline bool
1465 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1466 { return !__a; }
1467
1468 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1469 inline bool
1470 operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1471 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1472 { return __a.get() != __b.get(); }
1473
1474 template<typename _Tp, _Lock_policy _Lp>
1475 inline bool
1476 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1477 { return (bool)__a; }
1478
1479 template<typename _Tp, _Lock_policy _Lp>
1480 inline bool
1481 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1482 { return (bool)__a; }
1483
1484 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1485 inline bool
1486 operator<(const __shared_ptr<_Tp, _Lp>& __a,
1487 const __shared_ptr<_Up, _Lp>& __b) noexcept
1488 {
1489 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1490 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
1491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
1492 return less<_Vp>()(__a.get(), __b.get());
1493 }
1494
1495 template<typename _Tp, _Lock_policy _Lp>
1496 inline bool
1497 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1498 {
1499 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1500 return less<_Tp_elt*>()(__a.get(), nullptr);
1501 }
1502
1503 template<typename _Tp, _Lock_policy _Lp>
1504 inline bool
1505 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1506 {
1507 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1508 return less<_Tp_elt*>()(nullptr, __a.get());
1509 }
1510
1511 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1512 inline bool
1513 operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1514 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1515 { return !(__b < __a); }
1516
1517 template<typename _Tp, _Lock_policy _Lp>
1518 inline bool
1519 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1520 { return !(nullptr < __a); }
1521
1522 template<typename _Tp, _Lock_policy _Lp>
1523 inline bool
1524 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1525 { return !(__a < nullptr); }
1526
1527 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1528 inline bool
1529 operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1530 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1531 { return (__b < __a); }
1532
1533 template<typename _Tp, _Lock_policy _Lp>
1534 inline bool
1535 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1536 { return nullptr < __a; }
1537
1538 template<typename _Tp, _Lock_policy _Lp>
1539 inline bool
1540 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1541 { return __a < nullptr; }
1542
1543 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1544 inline bool
1545 operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1546 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1547 { return !(__a < __b); }
1548
1549 template<typename _Tp, _Lock_policy _Lp>
1550 inline bool
1551 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1552 { return !(__a < nullptr); }
1553
1554 template<typename _Tp, _Lock_policy _Lp>
1555 inline bool
1556 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1557 { return !(nullptr < __a); }
1558#endif // three-way comparison
1559
1560 // 20.7.2.2.8 shared_ptr specialized algorithms.
1561 template<typename _Tp, _Lock_policy _Lp>
1562 inline void
1563 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1564 { __a.swap(__b); }
1565
1566 // 20.7.2.2.9 shared_ptr casts
1567
1568 // The seemingly equivalent code:
1569 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1570 // will eventually result in undefined behaviour, attempting to
1571 // delete the same object twice.
1572 /// static_pointer_cast
1573 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1574 inline __shared_ptr<_Tp, _Lp>
1575 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1576 {
1577 using _Sp = __shared_ptr<_Tp, _Lp>;
1578 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
1579 }
1580
1581 // The seemingly equivalent code:
1582 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1583 // will eventually result in undefined behaviour, attempting to
1584 // delete the same object twice.
1585 /// const_pointer_cast
1586 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1587 inline __shared_ptr<_Tp, _Lp>
1588 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1589 {
1590 using _Sp = __shared_ptr<_Tp, _Lp>;
1591 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
1592 }
1593
1594 // The seemingly equivalent code:
1595 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1596 // will eventually result in undefined behaviour, attempting to
1597 // delete the same object twice.
1598 /// dynamic_pointer_cast
1599 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1600 inline __shared_ptr<_Tp, _Lp>
1601 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1602 {
1603 using _Sp = __shared_ptr<_Tp, _Lp>;
1604 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
1605 return _Sp(__r, __p);
1606 return _Sp();
1607 }
1608
1609#if __cplusplus201703L > 201402L
1610 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1611 inline __shared_ptr<_Tp, _Lp>
1612 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1613 {
1614 using _Sp = __shared_ptr<_Tp, _Lp>;
1615 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
1616 }
1617#endif
1618
1619 template<typename _Tp, _Lock_policy _Lp>
1620 class __weak_ptr
1621 {
1622 template<typename _Yp, typename _Res = void>
1623 using _Compatible = typename
1624 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1625
1626 // Constraint for assignment from shared_ptr and weak_ptr:
1627 template<typename _Yp>
1628 using _Assignable = _Compatible<_Yp, __weak_ptr&>;
1629
1630 public:
1631 using element_type = typename remove_extent<_Tp>::type;
1632
1633 constexpr __weak_ptr() noexcept
1634 : _M_ptr(nullptr), _M_refcount()
1635 { }
1636
1637 __weak_ptr(const __weak_ptr&) noexcept = default;
1638
1639 ~__weak_ptr() = default;
1640
1641 // The "obvious" converting constructor implementation:
1642 //
1643 // template<typename _Tp1>
1644 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1645 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1646 // { }
1647 //
1648 // has a serious problem.
1649 //
1650 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1651 // conversion may require access to *__r._M_ptr (virtual inheritance).
1652 //
1653 // It is not possible to avoid spurious access violations since
1654 // in multithreaded programs __r._M_ptr may be invalidated at any point.
1655 template<typename _Yp, typename = _Compatible<_Yp>>
1656 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1657 : _M_refcount(__r._M_refcount)
1658 { _M_ptr = __r.lock().get(); }
1659
1660 template<typename _Yp, typename = _Compatible<_Yp>>
1661 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1662 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1663 { }
1664
1665 __weak_ptr(__weak_ptr&& __r) noexcept
1666 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
1667 { __r._M_ptr = nullptr; }
1668
1669 template<typename _Yp, typename = _Compatible<_Yp>>
1670 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1671 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
1672 { __r._M_ptr = nullptr; }
1673
1674 __weak_ptr&
1675 operator=(const __weak_ptr& __r) noexcept = default;
1676
1677 template<typename _Yp>
1678 _Assignable<_Yp>
1679 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1680 {
1681 _M_ptr = __r.lock().get();
1682 _M_refcount = __r._M_refcount;
1683 return *this;
1684 }
1685
1686 template<typename _Yp>
1687 _Assignable<_Yp>
1688 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1689 {
1690 _M_ptr = __r._M_ptr;
1691 _M_refcount = __r._M_refcount;
1692 return *this;
1693 }
1694
1695 __weak_ptr&
1696 operator=(__weak_ptr&& __r) noexcept
1697 {
1698 _M_ptr = __r._M_ptr;
1699 _M_refcount = std::move(__r._M_refcount);
1700 __r._M_ptr = nullptr;
1701 return *this;
1702 }
1703
1704 template<typename _Yp>
1705 _Assignable<_Yp>
1706 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1707 {
1708 _M_ptr = __r.lock().get();
1709 _M_refcount = std::move(__r._M_refcount);
1710 __r._M_ptr = nullptr;
1711 return *this;
1712 }
1713
1714 __shared_ptr<_Tp, _Lp>
1715 lock() const noexcept
1716 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
1717
1718 long
1719 use_count() const noexcept
1720 { return _M_refcount._M_get_use_count(); }
1721
1722 bool
1723 expired() const noexcept
1724 { return _M_refcount._M_get_use_count() == 0; }
1725
1726 template<typename _Tp1>
1727 bool
1728 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
1729 { return _M_refcount._M_less(__rhs._M_refcount); }
1730
1731 template<typename _Tp1>
1732 bool
1733 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
1734 { return _M_refcount._M_less(__rhs._M_refcount); }
1735
1736 void
1737 reset() noexcept
1738 { __weak_ptr().swap(*this); }
1739
1740 void
1741 swap(__weak_ptr& __s) noexcept
1742 {
1743 std::swap(_M_ptr, __s._M_ptr);
1744 _M_refcount._M_swap(__s._M_refcount);
1745 }
1746
1747 private:
1748 // Used by __enable_shared_from_this.
1749 void
1750 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1751 {
1752 if (use_count() == 0)
1753 {
1754 _M_ptr = __ptr;
1755 _M_refcount = __refcount;
1756 }
1757 }
1758
1759 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1760 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1761 friend class __enable_shared_from_this<_Tp, _Lp>;
1762 friend class enable_shared_from_this<_Tp>;
1763
1764 element_type* _M_ptr; // Contained pointer.
1765 __weak_count<_Lp> _M_refcount; // Reference counter.
1766 };
1767
1768 // 20.7.2.3.6 weak_ptr specialized algorithms.
1769 template<typename _Tp, _Lock_policy _Lp>
1770 inline void
1771 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1772 { __a.swap(__b); }
1773
1774 template<typename _Tp, typename _Tp1>
1775 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1776 {
1777 bool
1778 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
1779 { return __lhs.owner_before(__rhs); }
1780
1781 bool
1782 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
1783 { return __lhs.owner_before(__rhs); }
1784
1785 bool
1786 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
1787 { return __lhs.owner_before(__rhs); }
1788 };
1789
1790 template<>
1791 struct _Sp_owner_less<void, void>
1792 {
1793 template<typename _Tp, typename _Up>
1794 auto
1795 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
1796 -> decltype(__lhs.owner_before(__rhs))
1797 { return __lhs.owner_before(__rhs); }
1798
1799 using is_transparent = void;
1800 };
1801
1802 template<typename _Tp, _Lock_policy _Lp>
1803 struct owner_less<__shared_ptr<_Tp, _Lp>>
1804 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1805 { };
1806
1807 template<typename _Tp, _Lock_policy _Lp>
1808 struct owner_less<__weak_ptr<_Tp, _Lp>>
1809 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1810 { };
1811
1812
1813 template<typename _Tp, _Lock_policy _Lp>
1814 class __enable_shared_from_this
1815 {
1816 protected:
1817 constexpr __enable_shared_from_this() noexcept { }
1818
1819 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1820
1821 __enable_shared_from_this&
1822 operator=(const __enable_shared_from_this&) noexcept
1823 { return *this; }
1824
1825 ~__enable_shared_from_this() { }
1826
1827 public:
1828 __shared_ptr<_Tp, _Lp>
1829 shared_from_this()
1830 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1831
1832 __shared_ptr<const _Tp, _Lp>
1833 shared_from_this() const
1834 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1835
1836#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
1837 __weak_ptr<_Tp, _Lp>
1838 weak_from_this() noexcept
1839 { return this->_M_weak_this; }
1840
1841 __weak_ptr<const _Tp, _Lp>
1842 weak_from_this() const noexcept
1843 { return this->_M_weak_this; }
1844#endif
1845
1846 private:
1847 template<typename _Tp1>
1848 void
1849 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1850 { _M_weak_this._M_assign(__p, __n); }
1851
1852 friend const __enable_shared_from_this*
1853 __enable_shared_from_this_base(const __shared_count<_Lp>&,
1854 const __enable_shared_from_this* __p)
1855 { return __p; }
1856
1857 template<typename, _Lock_policy>
1858 friend class __shared_ptr;
1859
1860 mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
1861 };
1862
1863 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1864 typename _Alloc, typename... _Args>
1865 inline __shared_ptr<_Tp, _Lp>
1866 __allocate_shared(const _Alloc& __a, _Args&&... __args)
1867 {
1868 return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
1869 std::forward<_Args>(__args)...);
1870 }
1871
1872 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1873 typename... _Args>
1874 inline __shared_ptr<_Tp, _Lp>
1875 __make_shared(_Args&&... __args)
1876 {
1877 typedef typename std::remove_const<_Tp>::type _Tp_nc;
1878 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1879 std::forward<_Args>(__args)...);
1880 }
1881
1882 /// std::hash specialization for __shared_ptr.
1883 template<typename _Tp, _Lock_policy _Lp>
1884 struct hash<__shared_ptr<_Tp, _Lp>>
1885 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1886 {
1887 size_t
1888 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1889 {
1890 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
1891 __s.get());
1892 }
1893 };
1894
1895_GLIBCXX_END_NAMESPACE_VERSION
1896} // namespace
1897
1898#endif // _SHARED_PTR_BASE_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/allocated_ptr.h

1// Guarded Allocation -*- C++ -*-
2
3// Copyright (C) 2014-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/allocated_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _ALLOCATED_PTR_H1
31#define _ALLOCATED_PTR_H1 1
32
33#if __cplusplus201703L < 201103L
34# include <bits/c++0xwarning.h>
35#else
36# include <type_traits>
37# include <bits/ptr_traits.h>
38# include <bits/alloc_traits.h>
39
40namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /// Non-standard RAII type for managing pointers obtained from allocators.
45 template<typename _Alloc>
46 struct __allocated_ptr
47 {
48 using pointer = typename allocator_traits<_Alloc>::pointer;
49 using value_type = typename allocator_traits<_Alloc>::value_type;
50
51 /// Take ownership of __ptr
52 __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept
53 : _M_alloc(std::__addressof(__a)), _M_ptr(__ptr)
54 { }
55
56 /// Convert __ptr to allocator's pointer type and take ownership of it
57 template<typename _Ptr,
58 typename _Req = _Require<is_same<_Ptr, value_type*>>>
59 __allocated_ptr(_Alloc& __a, _Ptr __ptr)
60 : _M_alloc(std::__addressof(__a)),
61 _M_ptr(pointer_traits<pointer>::pointer_to(*__ptr))
62 { }
63
64 /// Transfer ownership of the owned pointer
65 __allocated_ptr(__allocated_ptr&& __gd) noexcept
66 : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr)
67 { __gd._M_ptr = nullptr; }
68
69 /// Deallocate the owned pointer
70 ~__allocated_ptr()
71 {
72 if (_M_ptr != nullptr)
73 std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1);
74 }
75
76 /// Release ownership of the owned pointer
77 __allocated_ptr&
78 operator=(std::nullptr_t) noexcept
79 {
80 _M_ptr = nullptr;
81 return *this;
82 }
83
84 /// Get the address that the owned pointer refers to.
85 value_type* get() { return std::__to_address(_M_ptr); }
86
87 private:
88 _Alloc* _M_alloc;
89 pointer _M_ptr;
90 };
91
92 /// Allocate space for a single object using __a
93 template<typename _Alloc>
94 __allocated_ptr<_Alloc>
95 __allocate_guarded(_Alloc& __a)
96 {
97 return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
8
Calling 'allocator_traits::allocate'
14
Returned allocated memory
98 }
99
100_GLIBCXX_END_NAMESPACE_VERSION
101} // namespace std
102
103#endif
104#endif

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/alloc_traits.h

1// Allocator traits -*- C++ -*-
2
3// Copyright (C) 2011-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/alloc_traits.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _ALLOC_TRAITS_H1
31#define _ALLOC_TRAITS_H1 1
32
33#include <bits/stl_construct.h>
34#include <bits/memoryfwd.h>
35#if __cplusplus201703L >= 201103L
36# include <bits/allocator.h>
37# include <bits/ptr_traits.h>
38# include <ext/numeric_traits.h>
39#endif
40
41namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45#if __cplusplus201703L >= 201103L
46#define __cpp_lib_allocator_traits_is_always_equal201411 201411
47
48 struct __allocator_traits_base
49 {
50 template<typename _Tp, typename _Up, typename = void>
51 struct __rebind : __replace_first_arg<_Tp, _Up> { };
52
53 template<typename _Tp, typename _Up>
54 struct __rebind<_Tp, _Up,
55 __void_t<typename _Tp::template rebind<_Up>::other>>
56 { using type = typename _Tp::template rebind<_Up>::other; };
57
58 protected:
59 template<typename _Tp>
60 using __pointer = typename _Tp::pointer;
61 template<typename _Tp>
62 using __c_pointer = typename _Tp::const_pointer;
63 template<typename _Tp>
64 using __v_pointer = typename _Tp::void_pointer;
65 template<typename _Tp>
66 using __cv_pointer = typename _Tp::const_void_pointer;
67 template<typename _Tp>
68 using __pocca = typename _Tp::propagate_on_container_copy_assignment;
69 template<typename _Tp>
70 using __pocma = typename _Tp::propagate_on_container_move_assignment;
71 template<typename _Tp>
72 using __pocs = typename _Tp::propagate_on_container_swap;
73 template<typename _Tp>
74 using __equal = typename _Tp::is_always_equal;
75 };
76
77 template<typename _Alloc, typename _Up>
78 using __alloc_rebind
79 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
80
81 /**
82 * @brief Uniform interface to all allocator types.
83 * @ingroup allocators
84 */
85 template<typename _Alloc>
86 struct allocator_traits : __allocator_traits_base
87 {
88 /// The allocator type
89 typedef _Alloc allocator_type;
90 /// The allocated type
91 typedef typename _Alloc::value_type value_type;
92
93 /**
94 * @brief The allocator's pointer type.
95 *
96 * @c Alloc::pointer if that type exists, otherwise @c value_type*
97 */
98 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
99
100 private:
101 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
102 template<template<typename> class _Func, typename _Tp, typename = void>
103 struct _Ptr
104 {
105 using type = typename pointer_traits<pointer>::template rebind<_Tp>;
106 };
107
108 template<template<typename> class _Func, typename _Tp>
109 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
110 {
111 using type = _Func<_Alloc>;
112 };
113
114 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
115 template<typename _A2, typename _PtrT, typename = void>
116 struct _Diff
117 { using type = typename pointer_traits<_PtrT>::difference_type; };
118
119 template<typename _A2, typename _PtrT>
120 struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
121 { using type = typename _A2::difference_type; };
122
123 // Select _A2::size_type or make_unsigned<_DiffT>::type
124 template<typename _A2, typename _DiffT, typename = void>
125 struct _Size : make_unsigned<_DiffT> { };
126
127 template<typename _A2, typename _DiffT>
128 struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
129 { using type = typename _A2::size_type; };
130
131 public:
132 /**
133 * @brief The allocator's const pointer type.
134 *
135 * @c Alloc::const_pointer if that type exists, otherwise
136 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
137 */
138 using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
139
140 /**
141 * @brief The allocator's void pointer type.
142 *
143 * @c Alloc::void_pointer if that type exists, otherwise
144 * <tt> pointer_traits<pointer>::rebind<void> </tt>
145 */
146 using void_pointer = typename _Ptr<__v_pointer, void>::type;
147
148 /**
149 * @brief The allocator's const void pointer type.
150 *
151 * @c Alloc::const_void_pointer if that type exists, otherwise
152 * <tt> pointer_traits<pointer>::rebind<const void> </tt>
153 */
154 using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
155
156 /**
157 * @brief The allocator's difference type
158 *
159 * @c Alloc::difference_type if that type exists, otherwise
160 * <tt> pointer_traits<pointer>::difference_type </tt>
161 */
162 using difference_type = typename _Diff<_Alloc, pointer>::type;
163
164 /**
165 * @brief The allocator's size type
166 *
167 * @c Alloc::size_type if that type exists, otherwise
168 * <tt> make_unsigned<difference_type>::type </tt>
169 */
170 using size_type = typename _Size<_Alloc, difference_type>::type;
171
172 /**
173 * @brief How the allocator is propagated on copy assignment
174 *
175 * @c Alloc::propagate_on_container_copy_assignment if that type exists,
176 * otherwise @c false_type
177 */
178 using propagate_on_container_copy_assignment
179 = __detected_or_t<false_type, __pocca, _Alloc>;
180
181 /**
182 * @brief How the allocator is propagated on move assignment
183 *
184 * @c Alloc::propagate_on_container_move_assignment if that type exists,
185 * otherwise @c false_type
186 */
187 using propagate_on_container_move_assignment
188 = __detected_or_t<false_type, __pocma, _Alloc>;
189
190 /**
191 * @brief How the allocator is propagated on swap
192 *
193 * @c Alloc::propagate_on_container_swap if that type exists,
194 * otherwise @c false_type
195 */
196 using propagate_on_container_swap
197 = __detected_or_t<false_type, __pocs, _Alloc>;
198
199 /**
200 * @brief Whether all instances of the allocator type compare equal.
201 *
202 * @c Alloc::is_always_equal if that type exists,
203 * otherwise @c is_empty<Alloc>::type
204 */
205 using is_always_equal
206 = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
207
208 template<typename _Tp>
209 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
210 template<typename _Tp>
211 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
212
213 private:
214 template<typename _Alloc2>
215 static constexpr auto
216 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
217 -> decltype(__a.allocate(__n, __hint))
218 { return __a.allocate(__n, __hint); }
219
220 template<typename _Alloc2>
221 static constexpr pointer
222 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
223 { return __a.allocate(__n); }
224
225 template<typename _Tp, typename... _Args>
226 struct __construct_helper
227 {
228 template<typename _Alloc2,
229 typename = decltype(std::declval<_Alloc2*>()->construct(
230 std::declval<_Tp*>(), std::declval<_Args>()...))>
231 static true_type __test(int);
232
233 template<typename>
234 static false_type __test(...);
235
236 using type = decltype(__test<_Alloc>(0));
237 };
238
239 template<typename _Tp, typename... _Args>
240 using __has_construct
241 = typename __construct_helper<_Tp, _Args...>::type;
242
243 template<typename _Tp, typename... _Args>
244 static _GLIBCXX14_CONSTEXPRconstexpr _Require<__has_construct<_Tp, _Args...>>
245 _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
246 noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
247 { __a.construct(__p, std::forward<_Args>(__args)...); }
248
249 template<typename _Tp, typename... _Args>
250 static _GLIBCXX14_CONSTEXPRconstexpr
251 _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
252 is_constructible<_Tp, _Args...>>>
253 _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
254 noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
255 {
256#if __cplusplus201703L <= 201703L
257 ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
258#else
259 std::construct_at(__p, std::forward<_Args>(__args)...);
260#endif
261 }
262
263 template<typename _Alloc2, typename _Tp>
264 static _GLIBCXX14_CONSTEXPRconstexpr auto
265 _S_destroy(_Alloc2& __a, _Tp* __p, int)
266 noexcept(noexcept(__a.destroy(__p)))
267 -> decltype(__a.destroy(__p))
268 { __a.destroy(__p); }
269
270 template<typename _Alloc2, typename _Tp>
271 static _GLIBCXX14_CONSTEXPRconstexpr void
272 _S_destroy(_Alloc2&, _Tp* __p, ...)
273 noexcept(std::is_nothrow_destructible<_Tp>::value)
274 { std::_Destroy(__p); }
275
276 template<typename _Alloc2>
277 static constexpr auto
278 _S_max_size(_Alloc2& __a, int)
279 -> decltype(__a.max_size())
280 { return __a.max_size(); }
281
282 template<typename _Alloc2>
283 static constexpr size_type
284 _S_max_size(_Alloc2&, ...)
285 {
286 // _GLIBCXX_RESOLVE_LIB_DEFECTS
287 // 2466. allocator_traits::max_size() default behavior is incorrect
288 return __gnu_cxx::__numeric_traits<size_type>::__max
289 / sizeof(value_type);
290 }
291
292 template<typename _Alloc2>
293 static constexpr auto
294 _S_select(_Alloc2& __a, int)
295 -> decltype(__a.select_on_container_copy_construction())
296 { return __a.select_on_container_copy_construction(); }
297
298 template<typename _Alloc2>
299 static constexpr _Alloc2
300 _S_select(_Alloc2& __a, ...)
301 { return __a; }
302
303 public:
304
305 /**
306 * @brief Allocate memory.
307 * @param __a An allocator.
308 * @param __n The number of objects to allocate space for.
309 *
310 * Calls @c a.allocate(n)
311 */
312 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
313 allocate(_Alloc& __a, size_type __n)
314 { return __a.allocate(__n); }
315
316 /**
317 * @brief Allocate memory.
318 * @param __a An allocator.
319 * @param __n The number of objects to allocate space for.
320 * @param __hint Aid to locality.
321 * @return Memory of suitable size and alignment for @a n objects
322 * of type @c value_type
323 *
324 * Returns <tt> a.allocate(n, hint) </tt> if that expression is
325 * well-formed, otherwise returns @c a.allocate(n)
326 */
327 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
328 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
329 { return _S_allocate(__a, __n, __hint, 0); }
330
331 /**
332 * @brief Deallocate memory.
333 * @param __a An allocator.
334 * @param __p Pointer to the memory to deallocate.
335 * @param __n The number of objects space was allocated for.
336 *
337 * Calls <tt> a.deallocate(p, n) </tt>
338 */
339 static _GLIBCXX20_CONSTEXPR void
340 deallocate(_Alloc& __a, pointer __p, size_type __n)
341 { __a.deallocate(__p, __n); }
342
343 /**
344 * @brief Construct an object of type @a _Tp
345 * @param __a An allocator.
346 * @param __p Pointer to memory of suitable size and alignment for Tp
347 * @param __args Constructor arguments.
348 *
349 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
350 * if that expression is well-formed, otherwise uses placement-new
351 * to construct an object of type @a _Tp at location @a __p from the
352 * arguments @a __args...
353 */
354 template<typename _Tp, typename... _Args>
355 static _GLIBCXX20_CONSTEXPR auto
356 construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
357 noexcept(noexcept(_S_construct(__a, __p,
358 std::forward<_Args>(__args)...)))
359 -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
360 { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
361
362 /**
363 * @brief Destroy an object of type @a _Tp
364 * @param __a An allocator.
365 * @param __p Pointer to the object to destroy
366 *
367 * Calls @c __a.destroy(__p) if that expression is well-formed,
368 * otherwise calls @c __p->~_Tp()
369 */
370 template<typename _Tp>
371 static _GLIBCXX20_CONSTEXPR void
372 destroy(_Alloc& __a, _Tp* __p)
373 noexcept(noexcept(_S_destroy(__a, __p, 0)))
374 { _S_destroy(__a, __p, 0); }
375
376 /**
377 * @brief The maximum supported allocation size
378 * @param __a An allocator.
379 * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
380 *
381 * Returns @c __a.max_size() if that expression is well-formed,
382 * otherwise returns @c numeric_limits<size_type>::max()
383 */
384 static _GLIBCXX20_CONSTEXPR size_type
385 max_size(const _Alloc& __a) noexcept
386 { return _S_max_size(__a, 0); }
387
388 /**
389 * @brief Obtain an allocator to use when copying a container.
390 * @param __rhs An allocator.
391 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
392 *
393 * Returns @c __rhs.select_on_container_copy_construction() if that
394 * expression is well-formed, otherwise returns @a __rhs
395 */
396 static _GLIBCXX20_CONSTEXPR _Alloc
397 select_on_container_copy_construction(const _Alloc& __rhs)
398 { return _S_select(__rhs, 0); }
399 };
400
401#if __cplusplus201703L > 201703L
402# define __cpp_lib_constexpr_dynamic_alloc 201907L
403#endif
404
405 /// Partial specialization for std::allocator.
406 template<typename _Tp>
407 struct allocator_traits<allocator<_Tp>>
408 {
409 /// The allocator type
410 using allocator_type = allocator<_Tp>;
411
412 /// The allocated type
413 using value_type = _Tp;
414
415 /// The allocator's pointer type.
416 using pointer = _Tp*;
417
418 /// The allocator's const pointer type.
419 using const_pointer = const _Tp*;
420
421 /// The allocator's void pointer type.
422 using void_pointer = void*;
423
424 /// The allocator's const void pointer type.
425 using const_void_pointer = const void*;
426
427 /// The allocator's difference type
428 using difference_type = std::ptrdiff_t;
429
430 /// The allocator's size type
431 using size_type = std::size_t;
432
433 /// How the allocator is propagated on copy assignment
434 using propagate_on_container_copy_assignment = false_type;
435
436 /// How the allocator is propagated on move assignment
437 using propagate_on_container_move_assignment = true_type;
438
439 /// How the allocator is propagated on swap
440 using propagate_on_container_swap = false_type;
441
442 /// Whether all instances of the allocator type compare equal.
443 using is_always_equal = true_type;
444
445 template<typename _Up>
446 using rebind_alloc = allocator<_Up>;
447
448 template<typename _Up>
449 using rebind_traits = allocator_traits<allocator<_Up>>;
450
451 /**
452 * @brief Allocate memory.
453 * @param __a An allocator.
454 * @param __n The number of objects to allocate space for.
455 *
456 * Calls @c a.allocate(n)
457 */
458 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
459 allocate(allocator_type& __a, size_type __n)
460 { return __a.allocate(__n); }
9
Calling 'new_allocator::allocate'
13
Returned allocated memory
461
462 /**
463 * @brief Allocate memory.
464 * @param __a An allocator.
465 * @param __n The number of objects to allocate space for.
466 * @param __hint Aid to locality.
467 * @return Memory of suitable size and alignment for @a n objects
468 * of type @c value_type
469 *
470 * Returns <tt> a.allocate(n, hint) </tt>
471 */
472 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
473 allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
474 {
475#if __cplusplus201703L <= 201703L
476 return __a.allocate(__n, __hint);
477#else
478 return __a.allocate(__n);
479#endif
480 }
481
482 /**
483 * @brief Deallocate memory.
484 * @param __a An allocator.
485 * @param __p Pointer to the memory to deallocate.
486 * @param __n The number of objects space was allocated for.
487 *
488 * Calls <tt> a.deallocate(p, n) </tt>
489 */
490 static _GLIBCXX20_CONSTEXPR void
491 deallocate(allocator_type& __a, pointer __p, size_type __n)
492 { __a.deallocate(__p, __n); }
493
494 /**
495 * @brief Construct an object of type `_Up`
496 * @param __a An allocator.
497 * @param __p Pointer to memory of suitable size and alignment for
498 * an object of type `_Up`.
499 * @param __args Constructor arguments.
500 *
501 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
502 * in C++11, C++14 and C++17. Changed in C++20 to call
503 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
504 */
505 template<typename _Up, typename... _Args>
506 static _GLIBCXX20_CONSTEXPR void
507 construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
508 _Args&&... __args)
509 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
510 {
511#if __cplusplus201703L <= 201703L
512 __a.construct(__p, std::forward<_Args>(__args)...);
513#else
514 std::construct_at(__p, std::forward<_Args>(__args)...);
515#endif
516 }
517
518 /**
519 * @brief Destroy an object of type @a _Up
520 * @param __a An allocator.
521 * @param __p Pointer to the object to destroy
522 *
523 * Calls @c __a.destroy(__p).
524 */
525 template<typename _Up>
526 static _GLIBCXX20_CONSTEXPR void
527 destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
528 noexcept(is_nothrow_destructible<_Up>::value)
529 {
530#if __cplusplus201703L <= 201703L
531 __a.destroy(__p);
532#else
533 std::destroy_at(__p);
534#endif
535 }
536
537 /**
538 * @brief The maximum supported allocation size
539 * @param __a An allocator.
540 * @return @c __a.max_size()
541 */
542 static _GLIBCXX20_CONSTEXPR size_type
543 max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
544 {
545#if __cplusplus201703L <= 201703L
546 return __a.max_size();
547#else
548 return size_t(-1) / sizeof(value_type);
549#endif
550 }
551
552 /**
553 * @brief Obtain an allocator to use when copying a container.
554 * @param __rhs An allocator.
555 * @return @c __rhs
556 */
557 static _GLIBCXX20_CONSTEXPR allocator_type
558 select_on_container_copy_construction(const allocator_type& __rhs)
559 { return __rhs; }
560 };
561
562#if __cplusplus201703L < 201703L
563 template<typename _Alloc>
564 inline void
565 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
566 { __one = __two; }
567
568 template<typename _Alloc>
569 inline void
570 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
571 { }
572#endif
573
574 template<typename _Alloc>
575 _GLIBCXX14_CONSTEXPRconstexpr inline void
576 __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
577 {
578 typedef allocator_traits<_Alloc> __traits;
579 typedef typename __traits::propagate_on_container_copy_assignment __pocca;
580#if __cplusplus201703L >= 201703L
581 if constexpr (__pocca::value)
582 __one = __two;
583#else
584 __do_alloc_on_copy(__one, __two, __pocca());
585#endif
586 }
587
588 template<typename _Alloc>
589 constexpr _Alloc
590 __alloc_on_copy(const _Alloc& __a)
591 {
592 typedef allocator_traits<_Alloc> __traits;
593 return __traits::select_on_container_copy_construction(__a);
594 }
595
596#if __cplusplus201703L < 201703L
597 template<typename _Alloc>
598 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
599 { __one = std::move(__two); }
600
601 template<typename _Alloc>
602 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
603 { }
604#endif
605
606 template<typename _Alloc>
607 _GLIBCXX14_CONSTEXPRconstexpr inline void
608 __alloc_on_move(_Alloc& __one, _Alloc& __two)
609 {
610 typedef allocator_traits<_Alloc> __traits;
611 typedef typename __traits::propagate_on_container_move_assignment __pocma;
612#if __cplusplus201703L >= 201703L
613 if constexpr (__pocma::value)
614 __one = std::move(__two);
615#else
616 __do_alloc_on_move(__one, __two, __pocma());
617#endif
618 }
619
620#if __cplusplus201703L < 201703L
621 template<typename _Alloc>
622 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
623 {
624 using std::swap;
625 swap(__one, __two);
626 }
627
628 template<typename _Alloc>
629 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
630 { }
631#endif
632
633 template<typename _Alloc>
634 _GLIBCXX14_CONSTEXPRconstexpr inline void
635 __alloc_on_swap(_Alloc& __one, _Alloc& __two)
636 {
637 typedef allocator_traits<_Alloc> __traits;
638 typedef typename __traits::propagate_on_container_swap __pocs;
639#if __cplusplus201703L >= 201703L
640 if constexpr (__pocs::value)
641 {
642 using std::swap;
643 swap(__one, __two);
644 }
645#else
646 __do_alloc_on_swap(__one, __two, __pocs());
647#endif
648 }
649
650 template<typename _Alloc, typename _Tp,
651 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
652 typename = void>
653 struct __is_alloc_insertable_impl
654 : false_type
655 { };
656
657 template<typename _Alloc, typename _Tp, typename _ValueT>
658 struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
659 __void_t<decltype(allocator_traits<_Alloc>::construct(
660 std::declval<_Alloc&>(), std::declval<_ValueT*>(),
661 std::declval<_Tp>()))>>
662 : true_type
663 { };
664
665 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
666 // (might be wrong if _Alloc::construct exists but is not constrained,
667 // i.e. actually trying to use it would still be invalid. Use with caution.)
668 template<typename _Alloc>
669 struct __is_copy_insertable
670 : __is_alloc_insertable_impl<_Alloc,
671 typename _Alloc::value_type const&>::type
672 { };
673
674 // std::allocator<_Tp> just requires CopyConstructible
675 template<typename _Tp>
676 struct __is_copy_insertable<allocator<_Tp>>
677 : is_copy_constructible<_Tp>
678 { };
679
680 // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
681 // (might be wrong if _Alloc::construct exists but is not constrained,
682 // i.e. actually trying to use it would still be invalid. Use with caution.)
683 template<typename _Alloc>
684 struct __is_move_insertable
685 : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
686 { };
687
688 // std::allocator<_Tp> just requires MoveConstructible
689 template<typename _Tp>
690 struct __is_move_insertable<allocator<_Tp>>
691 : is_move_constructible<_Tp>
692 { };
693
694 // Trait to detect Allocator-like types.
695 template<typename _Alloc, typename = void>
696 struct __is_allocator : false_type { };
697
698 template<typename _Alloc>
699 struct __is_allocator<_Alloc,
700 __void_t<typename _Alloc::value_type,
701 decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
702 : true_type { };
703
704 template<typename _Alloc>
705 using _RequireAllocator
706 = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
707
708 template<typename _Alloc>
709 using _RequireNotAllocator
710 = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
711#endif // C++11
712
713 /**
714 * Destroy a range of objects using the supplied allocator. For
715 * non-default allocators we do not optimize away invocation of
716 * destroy() even if _Tp has a trivial destructor.
717 */
718
719 template<typename _ForwardIterator, typename _Allocator>
720 void
721 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
722 _Allocator& __alloc)
723 {
724 for (; __first != __last; ++__first)
725#if __cplusplus201703L < 201103L
726 __alloc.destroy(std::__addressof(*__first));
727#else
728 allocator_traits<_Allocator>::destroy(__alloc,
729 std::__addressof(*__first));
730#endif
731 }
732
733 template<typename _ForwardIterator, typename _Tp>
734 inline void
735 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
736 allocator<_Tp>&)
737 {
738 _Destroy(__first, __last);
739 }
740
741_GLIBCXX_END_NAMESPACE_VERSION
742} // namespace std
743#endif // _ALLOC_TRAITS_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/ext/new_allocator.h

1// Allocator that wraps operator new -*- C++ -*-
2
3// Copyright (C) 2001-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file ext/new_allocator.h
26 * This file is a GNU extension to the Standard C++ Library.
27 */
28
29#ifndef _NEW_ALLOCATOR_H1
30#define _NEW_ALLOCATOR_H1 1
31
32#include <bits/c++config.h>
33#include <new>
34#include <bits/functexcept.h>
35#include <bits/move.h>
36#if __cplusplus201703L >= 201103L
37#include <type_traits>
38#endif
39
40namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /**
45 * @brief An allocator that uses global new, as per [20.4].
46 * @ingroup allocators
47 *
48 * This is precisely the allocator defined in the C++ Standard.
49 * - all allocation calls operator new
50 * - all deallocation calls operator delete
51 *
52 * @tparam _Tp Type of allocated object.
53 */
54 template<typename _Tp>
55 class new_allocator
56 {
57 public:
58 typedef _Tp value_type;
59 typedef std::size_t size_type;
60 typedef std::ptrdiff_t difference_type;
61#if __cplusplus201703L <= 201703L
62 typedef _Tp* pointer;
63 typedef const _Tp* const_pointer;
64 typedef _Tp& reference;
65 typedef const _Tp& const_reference;
66
67 template<typename _Tp1>
68 struct rebind
69 { typedef new_allocator<_Tp1> other; };
70#endif
71
72#if __cplusplus201703L >= 201103L
73 // _GLIBCXX_RESOLVE_LIB_DEFECTS
74 // 2103. propagate_on_container_move_assignment
75 typedef std::true_type propagate_on_container_move_assignment;
76#endif
77
78 _GLIBCXX20_CONSTEXPR
79 new_allocator() _GLIBCXX_USE_NOEXCEPTnoexcept { }
80
81 _GLIBCXX20_CONSTEXPR
82 new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPTnoexcept { }
83
84 template<typename _Tp1>
85 _GLIBCXX20_CONSTEXPR
86 new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPTnoexcept { }
87
88#if __cplusplus201703L <= 201703L
89 ~new_allocator() _GLIBCXX_USE_NOEXCEPTnoexcept { }
90
91 pointer
92 address(reference __x) const _GLIBCXX_NOEXCEPTnoexcept
93 { return std::__addressof(__x); }
94
95 const_pointer
96 address(const_reference __x) const _GLIBCXX_NOEXCEPTnoexcept
97 { return std::__addressof(__x); }
98#endif
99
100 // NB: __n is permitted to be 0. The C++ standard says nothing
101 // about what the return value is when __n == 0.
102 _GLIBCXX_NODISCARD[[__nodiscard__]] _Tp*
103 allocate(size_type __n, const void* = static_cast<const void*>(0))
104 {
105 if (__n > this->_M_max_size())
10
Taking false branch
106 std::__throw_bad_alloc();
107
108#if __cpp_aligned_new201606L
109 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
11
Taking false branch
110 {
111 std::align_val_t __al = std::align_val_t(alignof(_Tp));
112 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
113 }
114#endif
115 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
12
Memory is allocated
116 }
117
118 // __p is not permitted to be a null pointer.
119 void
120 deallocate(_Tp* __p, size_type __t)
121 {
122#if __cpp_aligned_new201606L
123 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
124 {
125 ::operator delete(__p,
126# if __cpp_sized_deallocation
127 __t * sizeof(_Tp),
128# endif
129 std::align_val_t(alignof(_Tp)));
130 return;
131 }
132#endif
133 ::operator delete(__p
134#if __cpp_sized_deallocation
135 , __t * sizeof(_Tp)
136#endif
137 );
138 }
139
140#if __cplusplus201703L <= 201703L
141 size_type
142 max_size() const _GLIBCXX_USE_NOEXCEPTnoexcept
143 { return _M_max_size(); }
144
145#if __cplusplus201703L >= 201103L
146 template<typename _Up, typename... _Args>
147 void
148 construct(_Up* __p, _Args&&... __args)
149 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
150 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
151
152 template<typename _Up>
153 void
154 destroy(_Up* __p)
155 noexcept(std::is_nothrow_destructible<_Up>::value)
156 { __p->~_Up(); }
157#else
158 // _GLIBCXX_RESOLVE_LIB_DEFECTS
159 // 402. wrong new expression in [some_] allocator::construct
160 void
161 construct(pointer __p, const _Tp& __val)
162 { ::new((void *)__p) _Tp(__val); }
163
164 void
165 destroy(pointer __p) { __p->~_Tp(); }
166#endif
167#endif // ! C++20
168
169 template<typename _Up>
170 friend _GLIBCXX20_CONSTEXPR bool
171 operator==(const new_allocator&, const new_allocator<_Up>&)
172 _GLIBCXX_NOTHROWnoexcept
173 { return true; }
174
175#if __cpp_impl_three_way_comparison < 201907L
176 template<typename _Up>
177 friend _GLIBCXX20_CONSTEXPR bool
178 operator!=(const new_allocator&, const new_allocator<_Up>&)
179 _GLIBCXX_NOTHROWnoexcept
180 { return false; }
181#endif
182
183 private:
184 _GLIBCXX_CONSTEXPRconstexpr size_type
185 _M_max_size() const _GLIBCXX_USE_NOEXCEPTnoexcept
186 {
187#if __PTRDIFF_MAX__9223372036854775807L < __SIZE_MAX__18446744073709551615UL
188 return std::size_t(__PTRDIFF_MAX__9223372036854775807L) / sizeof(_Tp);
189#else
190 return std::size_t(-1) / sizeof(_Tp);
191#endif
192 }
193 };
194
195_GLIBCXX_END_NAMESPACE_VERSION
196} // namespace
197
198#endif