Skip to content

Commit a8389da

Browse files
author
Dawn Perchik
committed
P0674r1 Extending make_shared to Support Arrays
Also fixes LWG2070. Editorial changes: Fixed English and formatting.
1 parent ee7cfd9 commit a8389da

File tree

1 file changed

+265
-29
lines changed

1 file changed

+265
-29
lines changed

source/utilities.tex

Lines changed: 265 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9571,9 +9571,29 @@
95719571

95729572
// \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation
95739573
template<class T, class... Args>
9574-
shared_ptr<T> make_shared(Args&&... args);
9574+
shared_ptr<T> make_shared(Args&&... args); // \tcode{T} is not array
95759575
template<class T, class A, class... Args>
9576-
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
9576+
shared_ptr<T> allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array
9577+
9578+
template<class T> shared_ptr<T> make_shared(size_t N); // \tcode{T} is \tcode{U[]}
9579+
template<class T, class A>
9580+
shared_ptr<T> allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]}
9581+
9582+
template<class T> shared_ptr<T> make_shared(); // \tcode{T} is \tcode{U[N]}
9583+
template<class T, class A>
9584+
shared_ptr<T> allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]}
9585+
9586+
template<class T>
9587+
shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[]}
9588+
template<class T, class A>
9589+
shared_ptr<T> allocate_shared(const A& a, size_t N,
9590+
const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[]}
9591+
9592+
template<class T> shared_ptr<T>
9593+
make_shared(const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[N]}
9594+
template<class T, class A>
9595+
shared_ptr<T> allocate_shared(const A& a,
9596+
const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[N]}
95779597

95789598
// \ref{util.smartptr.shared.cmp}, \tcode{shared_ptr} comparisons
95799599
template<class T, class U>
@@ -10136,54 +10156,270 @@
1013610156

1013710157
\rSec4[util.smartptr.shared.create]{\tcode{shared_ptr} creation}
1013810158

10159+
\pnum
10160+
The common requirements that apply to
10161+
all \tcode{make_shared} and \tcode{allocate_shared} overloads,
10162+
unless specified otherwise, are described below.
10163+
10164+
\indexlibrary{\idxcode{make_shared}}%
10165+
\indexlibrary{\idxcode{allocate_shared}}%
10166+
\begin{itemdecl}
10167+
template<class T, ...>
10168+
shared_ptr<T> make_shared(\placeholder{args});
10169+
template<class T, class A, ...>
10170+
shared_ptr<T> allocate_shared(const A& a, \placeholder{args});
10171+
\end{itemdecl}
10172+
10173+
\begin{itemdescr}
10174+
\pnum
10175+
\requires \tcode{A} shall be an allocator~(\ref{allocator.requirements}).
10176+
10177+
\pnum
10178+
\effects Allocates memory for an object of type \tcode{T}
10179+
(or \tcode{U[N]} when \tcode{T} is \tcode{U[]},
10180+
where \tcode{N} is determined from \placeholder{args} as specified by the concrete overload).
10181+
The object is initialized from \placeholder{args} as specified by the concrete overload.
10182+
The \tcode{allocate_shared} templates use a copy of \tcode{a}
10183+
(rebound for an unspecified \tcode{value_type}) to allocate memory.
10184+
If an exception is thrown, the functions have no effect.
10185+
10186+
\pnum
10187+
\returns A \tcode{shared_ptr} instance that stores and owns the address of
10188+
the newly constructed object.
10189+
10190+
\pnum
10191+
\postconditions \tcode{r.get() != 0 \&\& r.use_count() == 1},
10192+
where \tcode{r} is the return value.
10193+
10194+
\pnum
10195+
\throws \tcode{bad_alloc}, or
10196+
an exception thrown from \tcode{allocate} or from the initialization of the object.
10197+
10198+
\pnum
10199+
\remarks
10200+
\begin{itemize}
10201+
\item
10202+
Implementations should perform no more than one memory allocation.
10203+
\begin{note}
10204+
This provides efficiency equivalent to an intrusive smart pointer.
10205+
\end{note}
10206+
\item
10207+
When an object of an array type \tcode{U} is specified to have
10208+
an initial value of \tcode{u} (of the same type),
10209+
this shall be interpreted to mean that
10210+
each array element of the object has as its initial value
10211+
the corresponding element from \tcode{u}.
10212+
\item
10213+
When an object of an array type is specified to have
10214+
a default initial value,
10215+
this shall be interpreted to mean that each array element of the object
10216+
has a default initial value.
10217+
\item
10218+
When a (sub)object of a non-array type \tcode{U} is specified to have
10219+
an initial value of \tcode{v}, or \tcode{U(l...)},
10220+
where \tcode{l...} is a list of constructor arguments,
10221+
\tcode{make_shared} shall initialize this (sub)object
10222+
via the expression \tcode{::new(pv) U(v)} or \tcode{::new(pv) U(l...)} respectively,
10223+
where \tcode{pv} has type \tcode{void*} and points to storage
10224+
suitable to hold an object of type \tcode{U}.
10225+
\item
10226+
When a (sub)object of a non-array type \tcode{U} is specified to have
10227+
an initial value of \tcode{v}, or \tcode{U(l...)},
10228+
where \tcode{l...} is a list of constructor arguments,
10229+
\tcode{allocate_shared} shall initialize this (sub)object
10230+
via the expression
10231+
\begin{itemize}
10232+
\item \tcode{allocator_traits<A2>::construct(a2, pv, v)} or
10233+
\item \tcode{allocator_traits<A2>::construct(a2, pv, l...)}
10234+
\end{itemize}
10235+
respectively,
10236+
where \tcode{pv} points to storage
10237+
suitable to hold an object of type \tcode{U} and
10238+
\tcode{a2} of type \tcode{A2} is a rebound copy of
10239+
the allocator \tcode{a} passed to \tcode{allocate_shared}
10240+
such that its \tcode{value_type} is \tcode{U}.
10241+
\item
10242+
When a (sub)object of non-array type \tcode{U} is specified to have
10243+
a default initial value,
10244+
\tcode{make_shared} shall initialize this (sub)object
10245+
via the expression \tcode{::new(pv) U()},
10246+
where \tcode{pv} has type \tcode{void*} and points to storage
10247+
suitable to hold an object of type \tcode{U}.
10248+
\item
10249+
When a (sub)object of non-array type \tcode{U} is specified to have
10250+
a default initial value,
10251+
\tcode{allocate_shared} shall initialize this (sub)object
10252+
via the expression \tcode{allocator_traits<A2>::construct(a2, pv)},
10253+
where \tcode{pv} points to storage
10254+
suitable to hold an object of type \tcode{U} and
10255+
\tcode{a2} of type \tcode{A2} is a rebound copy of
10256+
the allocator \tcode{a} passed to \tcode{allocate_shared}
10257+
such that its \tcode{value_type} is \tcode{U}.
10258+
\item
10259+
Array elements are initialized in ascending order of their addresses.
10260+
\item
10261+
When the lifetime of the object managed by the return value ends, or
10262+
when the initialization of an array element throws an exception,
10263+
the initialized elements should be destroyed in the reverse order of their construction.
10264+
\end{itemize}
10265+
\begin{note}
10266+
These functions will typically allocate more memory than \tcode{sizeof(T)} to
10267+
allow for internal bookkeeping structures such as reference counts.
10268+
\end{note}
10269+
\end{itemdescr}
10270+
1013910271
\indexlibrary{\idxcode{make_shared}}%
1014010272
\indexlibrary{\idxcode{allocate_shared}}%
1014110273
\begin{itemdecl}
1014210274
template<class T, class... Args>
10143-
shared_ptr<T> make_shared(Args&&... args);
10275+
shared_ptr<T> make_shared(Args&&... args); // \tcode{T} is not array
1014410276
template<class T, class A, class... Args>
10145-
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
10277+
shared_ptr<T> allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array
1014610278
\end{itemdecl}
1014710279

1014810280
\begin{itemdescr}
1014910281
\pnum
10150-
\requires The expression \tcode{::new (pv) T(std::forward<Args>(args)...)},
10151-
where \tcode{pv} has type \tcode{void*} and points to storage suitable
10152-
to hold an object of type \tcode{T}, shall be well formed. \tcode{A} shall
10153-
be an allocator~(\ref{allocator.requirements}). The copy constructor
10154-
and destructor of \tcode{A} shall not throw exceptions.
10282+
\returns A \tcode{shared_ptr} to an object of type \tcode{T}
10283+
with an initial value \tcode{T(forward<Args>(args)...)}.
1015510284

1015610285
\pnum
10157-
\effects Allocates memory suitable for an object of type \tcode{T}
10158-
and constructs an object in that memory via the placement
10159-
\grammarterm{new-expression}
10160-
\tcode{::new (pv) T(std::forward<Args>(args)...)}.
10161-
The template \tcode{allocate_shared} uses a copy of \tcode{a} to
10162-
allocate memory. If an exception is thrown, the functions have no effect.
10286+
\remarks These overloads shall only participate in overload resolution
10287+
when \tcode{T} is not an array type.
10288+
The \tcode{shared_ptr} constructors called by these functions
10289+
enable \tcode{shared_from_this}
10290+
with the address of the newly constructed object of type \tcode{T}.
1016310291

1016410292
\pnum
10165-
\returns A \tcode{shared_ptr} instance that stores and owns
10166-
the address of the newly constructed object of type \tcode{T}.
10293+
\begin{example}
10294+
\begin{codeblock}
10295+
shared_ptr<int> p = make_shared<int>(); // \tcode{shared_ptr} to \tcode{int()}
10296+
shared_ptr<vector<int>> q = make_shared<vector<int>>(16, 1);
10297+
// \tcode{shared_ptr} to vector of \tcode{16} elements with value \tcode{1}
10298+
\end{codeblock}
10299+
\end{example}
10300+
\end{itemdescr}
1016710301

10302+
\indexlibrary{\idxcode{make_shared}}%
10303+
\indexlibrary{\idxcode{allocate_shared}}%
10304+
\begin{itemdecl}
10305+
template<class T> shared_ptr<T> make_shared(size_t N); // \tcode{T} is \tcode{U[]}
10306+
template<class T, class A>
10307+
shared_ptr<T> allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]}
10308+
\end{itemdecl}
10309+
10310+
\begin{itemdescr}
1016810311
\pnum
10169-
\postconditions \tcode{get() != 0 \&\& use_count() == 1}.
10312+
\returns A \tcode{shared_ptr} to an object of type \tcode{U[N]}
10313+
with a default initial value,
10314+
where \tcode{U} is \tcode{remove_extent_t<T>}.
1017010315

1017110316
\pnum
10172-
\throws \tcode{bad_alloc}, or an exception thrown from
10173-
\tcode{A::allocate} or from the constructor of \tcode{T}.
10317+
\remarks These overloads shall only participate in overload resolution
10318+
when \tcode{T} is of the form \tcode{U[]}.
1017410319

1017510320
\pnum
10176-
\remarks The \tcode{shared_ptr} constructor called by this function
10177-
enables \tcode{shared_from_this} with the address
10178-
of the newly constructed object of type \tcode{T}.
10179-
Implementations should
10180-
perform no more than one memory allocation. \begin{note} This provides
10181-
efficiency equivalent to an intrusive smart pointer. \end{note}
10321+
\begin{example}
10322+
\begin{codeblock}
10323+
shared_ptr<double[]> p = make_shared<double[]>(1024);
10324+
// \tcode{shared_ptr} to a value-initialized \tcode{double[1024]}
10325+
shared_ptr<double[][2][2]> q = make_shared<double[][2][2]>(6);
10326+
// \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]}
10327+
\end{codeblock}
10328+
\end{example}
10329+
\end{itemdescr}
10330+
10331+
\indexlibrary{\idxcode{make_shared}}%
10332+
\indexlibrary{\idxcode{allocate_shared}}%
10333+
\begin{itemdecl}
10334+
template<class T> shared_ptr<T> make_shared(); // \tcode{T} is \tcode{U[N]}
10335+
template<class T, class A>
10336+
shared_ptr<T> allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]}
10337+
\end{itemdecl}
10338+
10339+
\begin{itemdescr}
10340+
\pnum
10341+
\returns A \tcode{shared_ptr} to an object of type \tcode{T}
10342+
with a default initial value.
10343+
10344+
\pnum
10345+
\remarks These overloads shall only participate in overload resolution
10346+
when \tcode{T} is of the form \tcode{U[N]}.
1018210347

1018310348
\pnum
10184-
\begin{note} These functions will typically allocate more memory
10185-
than \tcode{sizeof(T)} to allow for internal bookkeeping structures such
10186-
as the reference counts. \end{note}
10349+
\begin{example}
10350+
\begin{codeblock}
10351+
shared_ptr<double[1024]> p = make_shared<double[1024]>();
10352+
// \tcode{shared_ptr} to a value-initialized \tcode{double[1024]}
10353+
shared_ptr<double[6][2][2]> q = make_shared<double[6][2][2]>();
10354+
// \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]}
10355+
\end{codeblock}
10356+
\end{example}
10357+
\end{itemdescr}
10358+
10359+
\indexlibrary{\idxcode{make_shared}}%
10360+
\indexlibrary{\idxcode{allocate_shared}}%
10361+
\begin{itemdecl}
10362+
template<class T>
10363+
shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[]}
10364+
template<class T, class A>
10365+
shared_ptr<T> allocate_shared(const A& a, size_t N,
10366+
const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[]}
10367+
\end{itemdecl}
10368+
10369+
\begin{itemdescr}
10370+
\pnum
10371+
\returns A \tcode{shared_ptr} to an object of type \tcode{U[N]},
10372+
where \tcode{U} is \tcode{remove_extent_t<T>} and
10373+
each array element has an initial value of \tcode{u}.
10374+
10375+
\pnum
10376+
\remarks These overloads shall only participate in overload resolution
10377+
when \tcode{T} is of the form \tcode{U[]}.
10378+
10379+
\pnum
10380+
\begin{example}
10381+
\begin{codeblock}
10382+
shared_ptr<double[]> p = make_shared<double[]>(1024, 1.0);
10383+
// \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0}
10384+
shared_ptr<double[][2]> q = make_shared<double[][2]>(6, {1.0, 0.0});
10385+
// \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}}
10386+
shared_ptr<vector<int>[]> r = make_shared<vector<int>[]>(4, {1, 2});
10387+
// \tcode{shared_ptr} to a \tcode{vector<int>[4]}, where each vector has contents \tcode{\{1, 2\}}
10388+
\end{codeblock}
10389+
\end{example}
10390+
\end{itemdescr}
10391+
10392+
\indexlibrary{\idxcode{make_shared}}%
10393+
\indexlibrary{\idxcode{allocate_shared}}%
10394+
\begin{itemdecl}
10395+
template<class T>
10396+
shared_ptr<T> make_shared(const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[N]}
10397+
template<class T, class A>
10398+
shared_ptr<T> allocate_shared(const A& a,
10399+
const remove_extent_t<T>& u); // \tcode{T} is \tcode{U[N]}
10400+
\end{itemdecl}
10401+
10402+
\begin{itemdescr}
10403+
\pnum
10404+
\returns A \tcode{shared_ptr} to an object of type \tcode{T},
10405+
where each array element of type \tcode{remove_extent_t<T>}
10406+
has an initial value of \tcode{u}.
10407+
10408+
\pnum
10409+
\remarks These overloads shall only participate in overload resolution
10410+
when \tcode{T} is of the form \tcode{U[N]}.
10411+
10412+
\pnum
10413+
\begin{example}
10414+
\begin{codeblock}
10415+
shared_ptr<double[1024]> p = make_shared<double[1024]>(1.0);
10416+
// \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0}
10417+
shared_ptr<double[6][2]> q = make_shared<double[6][2]>({1.0, 0.0});
10418+
// \tcode{shared_ptr} to a \tcode{double[6][2]}, where each double[2] element is \tcode{\{1.0, 0.0\}}
10419+
shared_ptr<vector<int>[4]> r = make_shared<vector<int>[4]>({1, 2});
10420+
// \tcode{shared_ptr} to a \tcode{vector<int>[4]}, where each vector has contents \tcode{\{1, 2\}}
10421+
\end{codeblock}
10422+
\end{example}
1018710423
\end{itemdescr}
1018810424

1018910425
\rSec4[util.smartptr.shared.cmp]{\tcode{shared_ptr} comparison}

0 commit comments

Comments
 (0)