Topic: make_shared and inaccessible constructors


Author: Andrew Schepler <aschepler@gmail.com>
Date: Tue, 2 May 2017 14:25:24 -0700 (PDT)
Raw View
------=_Part_2199_790671560.1493760324057
Content-Type: multipart/alternative;
 boundary="----=_Part_2200_1258667116.1493760324057"

------=_Part_2200_1258667116.1493760324057
Content-Type: text/plain; charset=UTF-8

When a class is intended to be used only from std::shared_ptr, for instance
when using std::enable_shared_from_this, it can be desirable to enforce
this by making constructors and destructors private or protected.  A
working example:

class SharedClass :
    public std::enable_shared_from_this<SharedClass>
{
public:
    static std::shared_ptr<SharedClass> create()
    { return { new SharedClass, [](SharedClass* p) { delete p; } }; }
private:
    SharedClass() = default;
    ~SharedClass() = default;
    SharedClass(const SharedClass&) = delete;
    SharedClass& operator=(const SharedClass&) = delete;
};

However, this example misses out on the benefits of std::make_shared, like
doing just one allocation for both the control block and the pointed-to
object. We might like to rewrite the body of create() as { return
std::make_shared<SharedClass>(); }, but this is invalid as the required
constructor and destructor are inaccessible.  This can't be solved with a
friend declaration.  Although the Standard says make_shared will evaluate
::new(pv) T(forward<Args>(args)...), exactly what class or function will
use that expression is an implementation-specific detail.

Now, we can borrow an idea from boost::iterator_core_access.  The
documentation for class template boost::iterator_facade recommends users
implement the interface functions such as dereference() and increment() as
private, and add "friend class boost::iterator_core_access;".
 iterator_core_access itself merely wraps these interface functions and
exposes them to the actual various implementation classes that require them.

So I propose a new class std::shared_ptr_access with no public or protected
members, and to specify that for std::make_shared<T>(args...) and
std::alloc_shared<T>(a, args...), the expressions ::new(pv)
T(forward<Args>(args)...) and ptr->~T() must be well-formed in the context
of std::shared_ptr_access.

An implementation of std::shared_ptr_access might look like

namespace std {
    class shared_ptr_access
    {
        template <typename _T, typename ... _Args>
        static _T* __construct(void* __pv, _Args&& ... __args)
        { return ::new(__pv) _T(forward<_Args>(__args)...); }

        template <typename _T>
        static void __destroy(_T* __ptr) { __ptr->~_T(); }

        template <typename _T, typename _A>
        friend class __shared_ptr_storage;
    };
}

where __shared_ptr_storage<T,A> is a hypothetical implementation detail
that requires access to shared_ptr_access::__construct and
shared_ptr_access::__destroy.  Multiple friend declarations in
shared_ptr_access may be appropriate.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1b481894-2c2e-44ae-aa6a-c6b6a051fc86%40isocpp.org.

------=_Part_2200_1258667116.1493760324057
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">When a class is intended to be used only from std::shared_=
ptr, for instance when using std::enable_shared_from_this, it can be desira=
ble to enforce this by making constructors and destructors private or prote=
cted. =C2=A0A working example:<div><br></div><div>class SharedClass :</div>=
<div>=C2=A0 =C2=A0 public std::enable_shared_from_this&lt;SharedClass&gt;</=
div><div>{</div><div>public:</div><div>=C2=A0 =C2=A0 static std::shared_ptr=
&lt;SharedClass&gt; create()</div><div>=C2=A0 =C2=A0 { return { new SharedC=
lass, [](SharedClass* p) { delete p; } }; }</div><div>private:</div><div>=
=C2=A0 =C2=A0 SharedClass() =3D default;</div><div>=C2=A0 =C2=A0 ~SharedCla=
ss() =3D default;</div><div>=C2=A0 =C2=A0 SharedClass(const SharedClass&amp=
;) =3D delete;</div><div>=C2=A0 =C2=A0 SharedClass&amp; operator=3D(const S=
haredClass&amp;) =3D delete;</div><div>};</div><div><br></div><div>However,=
 this example misses out on the benefits of std::make_shared, like doing ju=
st one allocation for both the control block and the pointed-to object. We =
might like to rewrite the body of create() as { return std::make_shared&lt;=
SharedClass&gt;(); }, but this is invalid as the required constructor and d=
estructor are inaccessible. =C2=A0This can&#39;t be solved with a friend de=
claration. =C2=A0Although the Standard says make_shared will evaluate ::new=
(pv) T(forward&lt;Args&gt;(args)...), exactly what class or function will u=
se that expression is an implementation-specific detail.</div><div><br></di=
v><div>Now, we can borrow an idea from boost::iterator_core_access. =C2=A0T=
he documentation for class template boost::iterator_facade recommends users=
 implement the interface functions such as dereference() and increment() as=
 private, and add &quot;friend class boost::iterator_core_access;&quot;. =
=C2=A0iterator_core_access itself merely wraps these interface functions an=
d exposes them to the actual various implementation classes that require th=
em.</div><div><br></div><div>So I propose a new class std::shared_ptr_acces=
s with no public or protected members, and to specify that for std::make_sh=
ared&lt;T&gt;(args...) and std::alloc_shared&lt;T&gt;(a, args...), the expr=
essions ::new(pv) T(forward&lt;Args&gt;(args)...) and ptr-&gt;~T() must be =
well-formed in the context of std::shared_ptr_access.</div><div><br></div><=
div>An implementation of std::shared_ptr_access might look like</div><div><=
br></div><div>namespace std {</div><div>=C2=A0 =C2=A0 class shared_ptr_acce=
ss</div><div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 template=
 &lt;typename _T, typename ... _Args&gt;<br></div><div>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 static _T* __construct(void* __pv, _Args&amp;&amp; ... __args)</div=
><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 { return ::new(__pv) _T(forward&lt;_Args&=
gt;(__args)...); }</div><div><br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 tem=
plate &lt;typename _T&gt;</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 static void=
 __destroy(_T* __ptr) { __ptr-&gt;~_T(); }</div><div><br></div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 template &lt;typename _T, typename _A&gt;</div><div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 friend class __shared_ptr_storage;</div><div>=
=C2=A0 =C2=A0 };</div><div>}</div><div><br></div><div>where __shared_ptr_st=
orage&lt;T,A&gt; is a hypothetical implementation detail that requires acce=
ss to shared_ptr_access::__construct and shared_ptr_access::__destroy. =C2=
=A0Multiple friend declarations in shared_ptr_access may be appropriate.</d=
iv></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1b481894-2c2e-44ae-aa6a-c6b6a051fc86%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1b481894-2c2e-44ae-aa6a-c6b6a051fc86=
%40isocpp.org</a>.<br />

------=_Part_2200_1258667116.1493760324057--

------=_Part_2199_790671560.1493760324057--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 2 May 2017 14:51:23 -0700 (PDT)
Raw View
------=_Part_2018_3292518.1493761883815
Content-Type: multipart/alternative;
 boundary="----=_Part_2019_999342494.1493761883815"

------=_Part_2019_999342494.1493761883815
Content-Type: text/plain; charset=UTF-8



On Tuesday, May 2, 2017 at 5:25:24 PM UTC-4, Andrew Schepler wrote:
>
> When a class is intended to be used only from std::shared_ptr, for
> instance when using std::enable_shared_from_this, it can be desirable to
> enforce this by making constructors and destructors private or protected.
>  A working example:
>
> class SharedClass :
>     public std::enable_shared_from_this<SharedClass>
> {
> public:
>     static std::shared_ptr<SharedClass> create()
>     { return { new SharedClass, [](SharedClass* p) { delete p; } }; }
> private:
>     SharedClass() = default;
>     ~SharedClass() = default;
>     SharedClass(const SharedClass&) = delete;
>     SharedClass& operator=(const SharedClass&) = delete;
> };
>
> However, this example misses out on the benefits of std::make_shared, like
> doing just one allocation for both the control block and the pointed-to
> object. We might like to rewrite the body of create() as { return
> std::make_shared<SharedClass>(); }, but this is invalid as the required
> constructor and destructor are inaccessible.  This can't be solved with a
> friend declaration.
>

One solution to this problem is to use a key type. This is a type which is
move/copyable, but whose default constructor is private. The key type is
made a friend of `create`, and your `SharedClass`'s (now public)
constructors all take this type as a parameter. This allows `create` to
create an instance of the key type, thus allowing it to construct
`SharedClass` instances.

And since this form of friendship is done through the type system,
`make_shared<SharedClass>` has the power to create such types, so long as
the caller can pass along an instance of the key type.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4d27c1a3-6d51-46cd-8776-a0796886b245%40isocpp.org.

------=_Part_2019_999342494.1493761883815
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, May 2, 2017 at 5:25:24 PM UTC-4, Andre=
w Schepler wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">When a class is intended to be used only from std::shared_ptr, for inst=
ance when using std::enable_shared_from_this, it can be desirable to enforc=
e this by making constructors and destructors private or protected. =C2=A0A=
 working example:<div><br></div><div>class SharedClass :</div><div>=C2=A0 =
=C2=A0 public std::enable_shared_from_this&lt;<wbr>SharedClass&gt;</div><di=
v>{</div><div>public:</div><div>=C2=A0 =C2=A0 static std::shared_ptr&lt;Sha=
redClass&gt; create()</div><div>=C2=A0 =C2=A0 { return { new SharedClass, [=
](SharedClass* p) { delete p; } }; }</div><div>private:</div><div>=C2=A0 =
=C2=A0 SharedClass() =3D default;</div><div>=C2=A0 =C2=A0 ~SharedClass() =
=3D default;</div><div>=C2=A0 =C2=A0 SharedClass(const SharedClass&amp;) =
=3D delete;</div><div>=C2=A0 =C2=A0 SharedClass&amp; operator=3D(const Shar=
edClass&amp;) =3D delete;</div><div>};</div><div><br></div><div>However, th=
is example misses out on the benefits of std::make_shared, like doing just =
one allocation for both the control block and the pointed-to object. We mig=
ht like to rewrite the body of create() as { return std::make_shared&lt;Sha=
redClass&gt;(<wbr>); }, but this is invalid as the required constructor and=
 destructor are inaccessible. =C2=A0This can&#39;t be solved with a friend =
declaration.</div></div></blockquote><div><br>One solution to this problem =
is to use a key type. This is a type which is move/copyable, but whose defa=
ult constructor is private. The key type is made a friend of `create`, and =
your `SharedClass`&#39;s (now public) constructors all take this type as a =
parameter. This allows `create` to create an instance of the key type, thus=
 allowing it to construct `SharedClass` instances.<br><br>And since this fo=
rm of friendship is done through the type system, `make_shared&lt;SharedCla=
ss&gt;` has the power to create such types, so long as the caller can pass =
along an instance of the key type.</div><br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/4d27c1a3-6d51-46cd-8776-a0796886b245%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4d27c1a3-6d51-46cd-8776-a0796886b245=
%40isocpp.org</a>.<br />

------=_Part_2019_999342494.1493761883815--

------=_Part_2018_3292518.1493761883815--

.


Author: dalboris@gmail.com
Date: Tue, 10 Jul 2018 05:24:49 -0700 (PDT)
Raw View
------=_Part_119729_626741178.1531225489171
Content-Type: multipart/alternative;
 boundary="----=_Part_119730_1711493510.1531225489172"

------=_Part_119730_1711493510.1531225489172
Content-Type: text/plain; charset="UTF-8"

I know that this thread is one year old, but I'd just like to say that I
find this proposal by Andrew extremely useful and elegant. The alternatives
are:

- Simply keep the constructors public, and rely on the developers not to
call them. Possibly error-prone on big projects.
- Keep the constructors public but using a PassKey idiom as suggested by
Nicol. This prevents developer mistakes, but still clutters the public
interface with what is supposed to be an implementation detail (the
constructors are still publicly visible on Doxygen, etc.)
- Make the constructors private, and in the implementation of
SharedClass::create() use an "enable_make_shared" nested class. This keeps
the public interface clean but seems an abuse of inheritance and in theory
requires the base class to have a virtual destructor.

For more details, many variants of these approaches are documented here:
https://stackoverflow.com/questions/8147027/how-do-i-call-stdmake-shared-on-a-class-with-only-protected-or-private-const

Instead, the proposal of Andrew seems to have none of the drawbacks, and
perfectly matches the desired semantics, which is: "our class should only
be created via make_shared", that is, the constructors of the class should
be private, and the class should befriend whoever make_shared delegates for
the construction.

On Tuesday, May 2, 2017 at 11:25:24 PM UTC+2, Andrew Schepler wrote:
>
> When a class is intended to be used only from std::shared_ptr, for
> instance when using std::enable_shared_from_this, it can be desirable to
> enforce this by making constructors and destructors private or protected.
>  A working example:
>
> class SharedClass :
>     public std::enable_shared_from_this<SharedClass>
> {
> public:
>     static std::shared_ptr<SharedClass> create()
>     { return { new SharedClass, [](SharedClass* p) { delete p; } }; }
> private:
>     SharedClass() = default;
>     ~SharedClass() = default;
>     SharedClass(const SharedClass&) = delete;
>     SharedClass& operator=(const SharedClass&) = delete;
> };
>
> However, this example misses out on the benefits of std::make_shared, like
> doing just one allocation for both the control block and the pointed-to
> object. We might like to rewrite the body of create() as { return
> std::make_shared<SharedClass>(); }, but this is invalid as the required
> constructor and destructor are inaccessible.  This can't be solved with a
> friend declaration.  Although the Standard says make_shared will evaluate
> ::new(pv) T(forward<Args>(args)...), exactly what class or function will
> use that expression is an implementation-specific detail.
>
> Now, we can borrow an idea from boost::iterator_core_access.  The
> documentation for class template boost::iterator_facade recommends users
> implement the interface functions such as dereference() and increment() as
> private, and add "friend class boost::iterator_core_access;".
>  iterator_core_access itself merely wraps these interface functions and
> exposes them to the actual various implementation classes that require them.
>
> So I propose a new class std::shared_ptr_access with no public or
> protected members, and to specify that for std::make_shared<T>(args...) and
> std::alloc_shared<T>(a, args...), the expressions ::new(pv)
> T(forward<Args>(args)...) and ptr->~T() must be well-formed in the context
> of std::shared_ptr_access.
>
> An implementation of std::shared_ptr_access might look like
>
> namespace std {
>     class shared_ptr_access
>     {
>         template <typename _T, typename ... _Args>
>         static _T* __construct(void* __pv, _Args&& ... __args)
>         { return ::new(__pv) _T(forward<_Args>(__args)...); }
>
>         template <typename _T>
>         static void __destroy(_T* __ptr) { __ptr->~_T(); }
>
>         template <typename _T, typename _A>
>         friend class __shared_ptr_storage;
>     };
> }
>
> where __shared_ptr_storage<T,A> is a hypothetical implementation detail
> that requires access to shared_ptr_access::__construct and
> shared_ptr_access::__destroy.  Multiple friend declarations in
> shared_ptr_access may be appropriate.
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/159cb55e-b60a-4bab-8fc3-9bc9eb102139%40isocpp.org.

------=_Part_119730_1711493510.1531225489172
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I know that this thread is one year old, but I&#39;d just =
like to say that I find this proposal by Andrew extremely useful and elegan=
t. The alternatives are:<div><br></div><div>- Simply keep the constructors =
public, and rely on the developers not to call them. Possibly error-prone o=
n big projects.</div><div>- Keep the constructors public but using a PassKe=
y idiom as suggested by Nicol. This prevents developer mistakes, but still =
clutters the public interface with what is supposed to be an implementation=
 detail (the constructors are still publicly visible on Doxygen, etc.)</div=
><div>- Make the constructors private, and in the implementation of SharedC=
lass::create() use an &quot;enable_make_shared&quot; nested class. This kee=
ps the public interface clean but seems an abuse of inheritance and in theo=
ry requires the base class to have a virtual destructor.</div><div><br></di=
v><div>For more details, many variants of these approaches are documented h=
ere: https://stackoverflow.com/questions/8147027/how-do-i-call-stdmake-shar=
ed-on-a-class-with-only-protected-or-private-const</div><div><br></div><div=
>Instead, the proposal of Andrew seems to have none of the drawbacks, and p=
erfectly matches the desired semantics, which is: &quot;our class should on=
ly be created via make_shared&quot;, that is, the constructors of the class=
 should be private, and the class should befriend whoever make_shared deleg=
ates for the construction.</div><div><br></div><div>On Tuesday, May 2, 2017=
 at 11:25:24 PM UTC+2, Andrew Schepler wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr">When a class is intended to be used only fr=
om std::shared_ptr, for instance when using std::enable_shared_from_this, i=
t can be desirable to enforce this by making constructors and destructors p=
rivate or protected. =C2=A0A working example:<div><br></div><div>class Shar=
edClass :</div><div>=C2=A0 =C2=A0 public std::enable_shared_from_this&lt;<w=
br>SharedClass&gt;</div><div>{</div><div>public:</div><div>=C2=A0 =C2=A0 st=
atic std::shared_ptr&lt;SharedClass&gt; create()</div><div>=C2=A0 =C2=A0 { =
return { new SharedClass, [](SharedClass* p) { delete p; } }; }</div><div>p=
rivate:</div><div>=C2=A0 =C2=A0 SharedClass() =3D default;</div><div>=C2=A0=
 =C2=A0 ~SharedClass() =3D default;</div><div>=C2=A0 =C2=A0 SharedClass(con=
st SharedClass&amp;) =3D delete;</div><div>=C2=A0 =C2=A0 SharedClass&amp; o=
perator=3D(const SharedClass&amp;) =3D delete;</div><div>};</div><div><br><=
/div><div>However, this example misses out on the benefits of std::make_sha=
red, like doing just one allocation for both the control block and the poin=
ted-to object. We might like to rewrite the body of create() as { return st=
d::make_shared&lt;SharedClass&gt;(<wbr>); }, but this is invalid as the req=
uired constructor and destructor are inaccessible. =C2=A0This can&#39;t be =
solved with a friend declaration. =C2=A0Although the Standard says make_sha=
red will evaluate ::new(pv) T(forward&lt;Args&gt;(args)...), exactly what c=
lass or function will use that expression is an implementation-specific det=
ail.</div><div><br></div><div>Now, we can borrow an idea from boost::iterat=
or_core_access. =C2=A0The documentation for class template boost::iterator_=
facade recommends users implement the interface functions such as dereferen=
ce() and increment() as private, and add &quot;friend class boost::iterator=
_core_access;&quot;. =C2=A0iterator_core_access itself merely wraps these i=
nterface functions and exposes them to the actual various implementation cl=
asses that require them.</div><div><br></div><div>So I propose a new class =
std::shared_ptr_access with no public or protected members, and to specify =
that for std::make_shared&lt;T&gt;(args...) and std::alloc_shared&lt;T&gt;(=
a, args...), the expressions ::new(pv) T(forward&lt;Args&gt;(args)...) and =
ptr-&gt;~T() must be well-formed in the context of std::shared_ptr_access.<=
/div><div><br></div><div>An implementation of std::shared_ptr_access might =
look like</div><div><br></div><div>namespace std {</div><div>=C2=A0 =C2=A0 =
class shared_ptr_access</div><div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 template &lt;typename _T, typename ... _Args&gt;<br></div><di=
v>=C2=A0 =C2=A0 =C2=A0 =C2=A0 static _T* __construct(void* __pv, _Args&amp;=
&amp; ... __args)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 { return ::new(__pv=
) _T(forward&lt;_Args&gt;(__args)...); }</div><div><br></div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 template &lt;typename _T&gt;</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 static void __destroy(_T* __ptr) { __ptr-&gt;~_T(); }</div><d=
iv><br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 template &lt;typename _T, typ=
ename _A&gt;</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 friend class __shared_pt=
r_storage;</div><div>=C2=A0 =C2=A0 };</div><div>}</div><div><br></div><div>=
where __shared_ptr_storage&lt;T,A&gt; is a hypothetical implementation deta=
il that requires access to shared_ptr_access::__construct and shared_ptr_ac=
cess::__destroy. =C2=A0Multiple friend declarations in shared_ptr_access ma=
y be appropriate.</div></div></blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/159cb55e-b60a-4bab-8fc3-9bc9eb102139%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/159cb55e-b60a-4bab-8fc3-9bc9eb102139=
%40isocpp.org</a>.<br />

------=_Part_119730_1711493510.1531225489172--

------=_Part_119729_626741178.1531225489171--

.


Author: Glen Fernandes <glen.fernandes@gmail.com>
Date: Thu, 12 Jul 2018 06:23:53 -0700 (PDT)
Raw View
------=_Part_70362_250667673.1531401833308
Content-Type: multipart/alternative;
 boundary="----=_Part_70363_1253187263.1531401833308"

------=_Part_70363_1253187263.1531401833308
Content-Type: text/plain; charset="UTF-8"

On Tuesday, July 10, 2018 at 8:24:49 AM UTC-4, dalb...@gmail.com wrote:
>
> I know that this thread is one year old, but I'd just like to say that I
> find this proposal by Andrew extremely useful and elegant. The alternatives
> are:
>
> - Simply keep the constructors public, and rely on the developers not to
> call them. Possibly error-prone on big projects.
> - Keep the constructors public but using a PassKey idiom as suggested by
> Nicol. This prevents developer mistakes, but still clutters the public
> interface with what is supposed to be an implementation detail (the
> constructors are still publicly visible on Doxygen, etc.)
> - Make the constructors private, and in the implementation of
> SharedClass::create() use an "enable_make_shared" nested class. This keeps
> the public interface clean but seems an abuse of inheritance and in theory
> requires the base class to have a virtual destructor.
>
>

There's also:
- Keep the constructors private, but leverage an Allocator that can
construct and use std::allocate_shared instead of std::make_shared.

LWG2070 has been resolved, std::allocate_shared is required to use
std::allocator_traits<Allocator>::construct instead of placement new.
e.g. Using his SharedClass example above, this works for the create()
function:

class SharedClass {
public:
    static std::shared_ptr<SharedClass> create() {
        struct A : std::allocator<SharedClass> {
            void construct(void* p) { ::new(p) SharedClass(); }
            void destroy(SharedClass* p) { p->~SharedClass(); }
        };
        return std::allocate_shared<SharedClass>(A());
    }
private:
    SharedClass() = default;
    ~SharedClass() = default;
};

And doesn't involve more than one allocation.

Glen

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c4bc1e5e-df46-4b3e-ab39-d40d52392233%40isocpp.org.

------=_Part_70363_1253187263.1531401833308
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, July 10, 2018 at 8:24:49 AM UTC-4, dalb...@gma=
il.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
I know that this thread is one year old, but I&#39;d just like to say that =
I find this proposal by Andrew extremely useful and elegant. The alternativ=
es are:<div><br></div><div>- Simply keep the constructors public, and rely =
on the developers not to call them. Possibly error-prone on big projects.</=
div><div>- Keep the constructors public but using a PassKey idiom as sugges=
ted by Nicol. This prevents developer mistakes, but still clutters the publ=
ic interface with what is supposed to be an implementation detail (the cons=
tructors are still publicly visible on Doxygen, etc.)</div><div>- Make the =
constructors private, and in the implementation of SharedClass::create() us=
e an &quot;enable_make_shared&quot; nested class. This keeps the public int=
erface clean but seems an abuse of inheritance and in theory requires the b=
ase class to have a virtual destructor.</div><div>=C2=A0<br></div></div></b=
lockquote><div><br></div><div>There&#39;s also:</div><div>- Keep the constr=
uctors private, but leverage an Allocator that can construct and use std::a=
llocate_shared instead of std::make_shared.</div><div><br></div><div>LWG207=
0 has been resolved, std::allocate_shared is required to use std::allocator=
_traits&lt;Allocator&gt;::construct instead of placement new.</div><div>e.g=
.. Using his SharedClass example above, this works for the create() function=
:<br></div><div><br></div><div><div>class SharedClass {</div><div>public:</=
div><div>=C2=A0 =C2=A0 static std::shared_ptr&lt;SharedClass&gt; create() {=
</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 struct A : std::allocator&lt;SharedC=
lass&gt; {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void constru=
ct(void* p) { ::new(p) SharedClass(); }</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 void destroy(SharedClass* p) { p-&gt;~SharedClass(); }</d=
iv><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 };</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 return std::allocate_shared&lt;SharedClass&gt;(A());</div><div>=C2=A0 =
=C2=A0 }</div><div>private:</div><div>=C2=A0 =C2=A0 SharedClass() =3D defau=
lt;</div><div>=C2=A0 =C2=A0 ~SharedClass() =3D default;</div><div>};</div><=
/div><div><br></div><div>And doesn&#39;t involve more than one allocation.<=
/div><div><br></div><div>Glen</div><div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/c4bc1e5e-df46-4b3e-ab39-d40d52392233%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c4bc1e5e-df46-4b3e-ab39-d40d52392233=
%40isocpp.org</a>.<br />

------=_Part_70363_1253187263.1531401833308--

------=_Part_70362_250667673.1531401833308--

.


Author: Glen Fernandes <glen.fernandes@gmail.com>
Date: Thu, 12 Jul 2018 06:41:57 -0700 (PDT)
Raw View
------=_Part_122668_1341913639.1531402918026
Content-Type: multipart/alternative;
 boundary="----=_Part_122669_59843891.1531402918026"

------=_Part_122669_59843891.1531402918026
Content-Type: text/plain; charset="UTF-8"

I wrote:
>
> e.g. Using his SharedClass example above, this works for the create()
> function:
>
>
I remembered how we actually specified things in P0674R1, so the following
is probably a better example instead:

class SharedClass {
public:
    static std::shared_ptr<SharedClass> create()
    { return std::allocate_shared<SharedClass>(A<SharedClass>()); }
private:
    template<class T> struct A : std::allocator<T> {
        void construct(void* p) { ::new(p) SharedClass(); }
        void destroy(SharedClass* p) { p->~SharedClass(); }
    };
    SharedClass() = default;
    ~SharedClass() = default;
};

i.e. We mandated rebind before construct.

In any case, not many lines of code to achieve the same thing (private
constructors, single allocation shared_ptr).

Glen

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f9955587-e274-4c17-870b-f82d4f8ff8b1%40isocpp.org.

------=_Part_122669_59843891.1531402918026
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><div>e.g. Using his SharedClass example above, this works for t=
he create() function:<br></div><div><br></div></div></blockquote><div><br><=
/div><div>I remembered how we actually specified things in P0674R1, so the =
following is probably a better example instead:=C2=A0</div><div>=C2=A0</div=
><div><div>class SharedClass {</div><div>public:</div><div>=C2=A0 =C2=A0 st=
atic std::shared_ptr&lt;SharedClass&gt; create()</div><div>=C2=A0 =C2=A0 { =
return std::allocate_shared&lt;SharedClass&gt;(A&lt;SharedClass&gt;()); }</=
div><div>private:</div><div>=C2=A0 =C2=A0 template&lt;class T&gt; struct A =
: std::allocator&lt;T&gt; {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 void cons=
truct(void* p) { ::new(p) SharedClass(); }</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 void destroy(SharedClass* p) { p-&gt;~SharedClass(); }</div><div>=C2=
=A0 =C2=A0 };</div><div>=C2=A0 =C2=A0 SharedClass() =3D default;</div><div>=
=C2=A0 =C2=A0 ~SharedClass() =3D default;</div><div>};</div></div><div><br>=
</div><div>i.e. We mandated rebind before construct.=C2=A0</div><div><br></=
div><div>In any case, not many lines of code to achieve the same thing (pri=
vate constructors, single allocation shared_ptr).</div><div><br></div><div>=
Glen</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/f9955587-e274-4c17-870b-f82d4f8ff8b1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f9955587-e274-4c17-870b-f82d4f8ff8b1=
%40isocpp.org</a>.<br />

------=_Part_122669_59843891.1531402918026--

------=_Part_122668_1341913639.1531402918026--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 12 Jul 2018 07:20:26 -0700 (PDT)
Raw View
------=_Part_98115_448428477.1531405226411
Content-Type: multipart/alternative;
 boundary="----=_Part_98116_753969777.1531405226411"

------=_Part_98116_753969777.1531405226411
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Fernandes wrote:
>
> In any case, not many lines of code to achieve the same thing (private
> constructors, single allocation shared_ptr).
>

A key type is just as easy to use, and *doesn't* require everyone to use
your specialized allocator type. There are advantages to being able to use
`std::allocator`.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c176784e-4482-442a-83d6-4b1d117e5422%40isocpp.org.

------=_Part_98116_753969777.1531405226411
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Ferna=
ndes wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><d=
iv>In any case, not many lines of code to achieve the same thing (private c=
onstructors, single allocation shared_ptr).</div></div></blockquote><div><b=
r></div><div>A key type is just as easy to use, and <i>doesn&#39;t</i> requ=
ire everyone to use your specialized allocator type. There are advantages t=
o being able to use `std::allocator`.<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/c176784e-4482-442a-83d6-4b1d117e5422%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c176784e-4482-442a-83d6-4b1d117e5422=
%40isocpp.org</a>.<br />

------=_Part_98116_753969777.1531405226411--

------=_Part_98115_448428477.1531405226411--

.


Author: Glen Fernandes <glen.fernandes@gmail.com>
Date: Thu, 12 Jul 2018 07:34:55 -0700 (PDT)
Raw View
------=_Part_136931_665158523.1531406095963
Content-Type: multipart/alternative;
 boundary="----=_Part_136932_1122942223.1531406095963"

------=_Part_136932_1122942223.1531406095963
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 10:20:26 AM UTC-4, Nicol Bolas wrote:
>
> On Thursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Fernandes wrote:
>>
>> In any case, not many lines of code to achieve the same thing (private
>> constructors, single allocation shared_ptr).
>>
>
> A key type is just as easy to use, and *doesn't* require everyone to use
> your specialized allocator type. There are advantages to being able to use
> `std::allocator`.
>

A key type would be easier to use.

There are advantages to both, depending on what the user needs: For
example, if the user wanted SharedClass to be Trivial, they wouldn't be
able to do that by providing a SharedClass constructor that accepted an
argument of a key type.  While SharedClass() = default; with a custom
allocator and std::allocate_shared would meet that requirement.

Glen

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1f8f65d4-71e2-4662-8043-822ae4aca5a9%40isocpp.org.

------=_Part_136932_1122942223.1531406095963
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 10:20:26 AM UTC-4, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On T=
hursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Fernandes wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
 #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>In any case, not many l=
ines of code to achieve the same thing (private constructors, single alloca=
tion shared_ptr).</div></div></blockquote><div><br></div><div>A key type is=
 just as easy to use, and <i>doesn&#39;t</i> require everyone to use your s=
pecialized allocator type. There are advantages to being able to use `std::=
allocator`.<br></div></div></blockquote><div><br></div><div>A key type woul=
d be easier to use.=C2=A0</div><div><br></div><div>There are advantages to =
both, depending on what the user needs: For example, if the user wanted Sha=
redClass to be Trivial, they wouldn&#39;t be able to do that by providing a=
 SharedClass constructor that accepted an argument of a key type.=C2=A0 Whi=
le SharedClass() =3D default; with a custom allocator and std::allocate_sha=
red would meet that requirement.</div><div><br></div><div>Glen</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1f8f65d4-71e2-4662-8043-822ae4aca5a9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1f8f65d4-71e2-4662-8043-822ae4aca5a9=
%40isocpp.org</a>.<br />

------=_Part_136932_1122942223.1531406095963--

------=_Part_136931_665158523.1531406095963--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 12 Jul 2018 08:24:45 -0700 (PDT)
Raw View
------=_Part_854_1107795295.1531409085166
Content-Type: multipart/alternative;
 boundary="----=_Part_855_409684964.1531409085166"

------=_Part_855_409684964.1531409085166
Content-Type: text/plain; charset="UTF-8"



On Thursday, July 12, 2018 at 10:34:56 AM UTC-4, Glen Fernandes wrote:
>
> On Thursday, July 12, 2018 at 10:20:26 AM UTC-4, Nicol Bolas wrote:
>>
>> On Thursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Fernandes wrote:
>>>
>>> In any case, not many lines of code to achieve the same thing (private
>>> constructors, single allocation shared_ptr).
>>>
>>
>> A key type is just as easy to use, and *doesn't* require everyone to use
>> your specialized allocator type. There are advantages to being able to use
>> `std::allocator`.
>>
>
> A key type would be easier to use.
>
> There are advantages to both, depending on what the user needs: For
> example, if the user wanted SharedClass to be Trivial, they wouldn't be
> able to do that by providing a SharedClass constructor that accepted an
> argument of a key type.  While SharedClass() = default; with a custom
> allocator and std::allocate_shared would meet that requirement.
>

What good is that? If the default constructor isn't public, then nobody can
actually trivially construct one. And if you use some creation function or
even `allocator::construct` to create it, it will almost certainly perform *value
initialization*, not leave the type uninitialized.

So why would you need a type to be Trivial with a private default
constructor?

Also, if you're using a custom allocator, types like `vector` which may
have optimized copy/move behavior for trivially copyable types cannot use
it, since they don't know if your `construct/destruct` methods call
`new/delete` or not. So there is an inherent disadvantage to using an
allocator to control *just* construction/destruction.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6d7bd148-73a1-4b0c-97a9-cdf453db8d18%40isocpp.org.

------=_Part_855_409684964.1531409085166
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Thursday, July 12, 2018 at 10:34:56 AM UTC-4, G=
len Fernandes wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Thursday, July 12, 2018 at 10:20:26 AM UTC-4, Nicol Bolas wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Thursday, July=
 12, 2018 at 9:41:58 AM UTC-4, Glen Fernandes wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>In any case, not many lines of code =
to achieve the same thing (private constructors, single allocation shared_p=
tr).</div></div></blockquote><div><br></div><div>A key type is just as easy=
 to use, and <i>doesn&#39;t</i> require everyone to use your specialized al=
locator type. There are advantages to being able to use `std::allocator`.<b=
r></div></div></blockquote><div><br></div><div>A key type would be easier t=
o use.=C2=A0</div><div><br></div><div>There are advantages to both, dependi=
ng on what the user needs: For example, if the user wanted SharedClass to b=
e Trivial, they wouldn&#39;t be able to do that by providing a SharedClass =
constructor that accepted an argument of a key type.=C2=A0 While SharedClas=
s() =3D default; with a custom allocator and std::allocate_shared would mee=
t that requirement.</div></div></blockquote><div><br></div><div>What good i=
s that? If the default constructor isn&#39;t public, then nobody can actual=
ly trivially construct one. And if you use some creation function or even `=
allocator::construct` to create it, it will almost certainly perform <i>val=
ue initialization</i>, not leave the type uninitialized.</div><div><br></di=
v><div>So why would you need a type to be Trivial with a private default co=
nstructor?<br></div><div><br></div><div>Also, if you&#39;re using a custom =
allocator, types like `vector` which may have optimized copy/move behavior =
for trivially copyable types cannot use it, since they don&#39;t know if yo=
ur `construct/destruct` methods call `new/delete` or not. So there is an in=
herent disadvantage to using an allocator to control <i>just</i> constructi=
on/destruction.<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6d7bd148-73a1-4b0c-97a9-cdf453db8d18%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6d7bd148-73a1-4b0c-97a9-cdf453db8d18=
%40isocpp.org</a>.<br />

------=_Part_855_409684964.1531409085166--

------=_Part_854_1107795295.1531409085166--

.


Author: Glen Fernandes <glen.fernandes@gmail.com>
Date: Thu, 12 Jul 2018 09:06:25 -0700 (PDT)
Raw View
------=_Part_137101_624098.1531411585754
Content-Type: multipart/alternative;
 boundary="----=_Part_137102_75561125.1531411585754"

------=_Part_137102_75561125.1531411585754
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 11:24:45 AM UTC-4, Nicol Bolas wrote:
>
>
> On Thursday, July 12, 2018 at 10:34:56 AM UTC-4, Glen Fernandes wrote:
>>
>> A key type would be easier to use.
>>
>> There are advantages to both, depending on what the user needs: For
>> example, if the user wanted SharedClass to be Trivial, they wouldn't be
>> able to do that by providing a SharedClass constructor that accepted an
>> argument of a key type.  While SharedClass() = default; with a custom
>> allocator and std::allocate_shared would meet that requirement.
>>
>
> What good is that? If the default constructor isn't public, then nobody
> can actually trivially construct one.
>

Certain C++ library implementations (including C++ standard library
implementations) special case trivial types. For example: libstdc++ will
only use __builtin_memmove in algorithms like std::copy when T is trivial
(not just if T is trivially-copy-assignable). In such cases, std::copy on
SharedClass* defined with a defaulted constructor that preserves triviality
could benefit from that.

And if you use some creation function or even `allocator::construct` to
> create it, it will almost certainly perform *value initialization*, not
> leave the type uninitialized.
>
>
If someone wanted that SharedClass::create() creation function to perform
default-initialization instead of value-initialization, using
std::allocate_shared with a custom allocator that constructs using
default-initialization is also one way of achieving that.

Glen

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/91d6b29f-3f04-4572-8ce6-25de5b0194c4%40isocpp.org.

------=_Part_137102_75561125.1531411585754
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 11:24:45 AM UTC-4, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>=
On Thursday, July 12, 2018 at 10:34:56 AM UTC-4, Glen Fernandes wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>A key type would b=
e easier to use.=C2=A0<br></div><div><br></div><div>There are advantages to=
 both, depending on what the user needs: For example, if the user wanted Sh=
aredClass to be Trivial, they wouldn&#39;t be able to do that by providing =
a SharedClass constructor that accepted an argument of a key type.=C2=A0 Wh=
ile SharedClass() =3D default; with a custom allocator and std::allocate_sh=
ared would meet that requirement.</div></div></blockquote><div><br></div><d=
iv>What good is that? If the default constructor isn&#39;t public, then nob=
ody can actually trivially construct one. </div></div></blockquote><div><br=
></div><div>Certain C++ library implementations (including C++ standard lib=
rary implementations) special case trivial types.=C2=A0For example: libstdc=
++ will only use __builtin_memmove in algorithms like std::copy when T is t=
rivial (not just if T is trivially-copy-assignable). In such cases, std::co=
py on SharedClass* defined with a defaulted constructor that preserves triv=
iality could benefit from that.</div><div><br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div>And if you use some creation fu=
nction or even `allocator::construct` to create it, it will almost certainl=
y perform <i>value initialization</i>, not leave the type uninitialized.</d=
iv><div><br></div></div></blockquote><div><br></div><div>If someone wanted =
that SharedClass::create() creation function to perform default-initializat=
ion instead of value-initialization, using std::allocate_shared with a cust=
om allocator that constructs using default-initialization is also one way o=
f achieving that.</div><div><br></div><div>Glen</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/91d6b29f-3f04-4572-8ce6-25de5b0194c4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/91d6b29f-3f04-4572-8ce6-25de5b0194c4=
%40isocpp.org</a>.<br />

------=_Part_137102_75561125.1531411585754--

------=_Part_137101_624098.1531411585754--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 12 Jul 2018 09:51:41 -0700 (PDT)
Raw View
------=_Part_2266_1244476016.1531414302204
Content-Type: multipart/alternative;
 boundary="----=_Part_2267_781337167.1531414302204"

------=_Part_2267_781337167.1531414302204
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 12:06:25 PM UTC-4, Glen Fernandes wrote:
>
> On Thursday, July 12, 2018 at 11:24:45 AM UTC-4, Nicol Bolas wrote:
>>
>>
>> On Thursday, July 12, 2018 at 10:34:56 AM UTC-4, Glen Fernandes wrote:
>>>
>>> A key type would be easier to use.
>>>
>>> There are advantages to both, depending on what the user needs: For
>>> example, if the user wanted SharedClass to be Trivial, they wouldn't be
>>> able to do that by providing a SharedClass constructor that accepted an
>>> argument of a key type.  While SharedClass() = default; with a custom
>>> allocator and std::allocate_shared would meet that requirement.
>>>
>>
>> What good is that? If the default constructor isn't public, then nobody
>> can actually trivially construct one.
>>
>
> Certain C++ library implementations (including C++ standard library
> implementations) special case trivial types. For example: libstdc++ will
> only use __builtin_memmove in algorithms like std::copy when T is trivial
> (not just if T is trivially-copy-assignable).
>

It should be based on TriviallyCopyable, not Trivial. As I understand it,
that's how it works in MSVC's standard library. In any case, that's the
only limitation on performing such byte-wise copy operations that the
standard imposes.

In such cases, std::copy on SharedClass* defined with a defaulted
> constructor that preserves triviality could benefit from that.
>

You can still use a key rather than an allocator. Just make your default
constructor private, and all those optimizations come back. After all, it's
not like `std::copy` is going to *call* the default constructor.

My point is that you shouldn't be using an allocator for this. The reason
is what I outlined: the kind of optimization you're talking about cannot be
done in `std::vector` if you are using a custom allocator that has its own
`construct/destruct` functions.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dc886c1b-444d-4dec-bed4-513ad8f58f37%40isocpp.org.

------=_Part_2267_781337167.1531414302204
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 12:06:25 PM UTC-4, Glen Fern=
andes wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">O=
n Thursday, July 12, 2018 at 11:24:45 AM UTC-4, Nicol Bolas wrote:<blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br>On Thursday, July 12, 2=
018 at 10:34:56 AM UTC-4, Glen Fernandes wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>A key type would be easier to use.=C2=A0<=
br></div><div><br></div><div>There are advantages to both, depending on wha=
t the user needs: For example, if the user wanted SharedClass to be Trivial=
, they wouldn&#39;t be able to do that by providing a SharedClass construct=
or that accepted an argument of a key type.=C2=A0 While SharedClass() =3D d=
efault; with a custom allocator and std::allocate_shared would meet that re=
quirement.</div></div></blockquote><div><br></div><div>What good is that? I=
f the default constructor isn&#39;t public, then nobody can actually trivia=
lly construct one. </div></div></blockquote><div><br></div><div>Certain C++=
 library implementations (including C++ standard library implementations) s=
pecial case trivial types.=C2=A0For example: libstdc++ will only use __buil=
tin_memmove in algorithms like std::copy when T is trivial (not just if T i=
s trivially-copy-assignable).</div></div></blockquote><div><br></div><div>I=
t should be based on TriviallyCopyable, not Trivial. As I understand it, th=
at&#39;s how it works in MSVC&#39;s standard library. In any case, that&#39=
;s the only limitation on performing such byte-wise copy operations that th=
e standard imposes.</div><div><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div>In such cases, std::copy on SharedClass* de=
fined with a defaulted constructor that preserves triviality could benefit =
from that.</div></div></blockquote><div><br></div><div>You can still use a =
key rather than an allocator. Just make your default constructor private, a=
nd all those optimizations come back. After all, it&#39;s not like `std::co=
py` is going to <i>call</i> the default constructor.</div><div><br></div><d=
iv>My point is that you shouldn&#39;t be using an allocator for this. The r=
eason is what I outlined: the kind of optimization you&#39;re talking about=
 cannot be done in `std::vector` if you are using a custom allocator that h=
as its own `construct/destruct` functions.</div><br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/dc886c1b-444d-4dec-bed4-513ad8f58f37%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dc886c1b-444d-4dec-bed4-513ad8f58f37=
%40isocpp.org</a>.<br />

------=_Part_2267_781337167.1531414302204--

------=_Part_2266_1244476016.1531414302204--

.


Author: Glen Fernandes <glen.fernandes@gmail.com>
Date: Thu, 12 Jul 2018 10:54:32 -0700 (PDT)
Raw View
------=_Part_123943_2033431296.1531418072190
Content-Type: multipart/alternative;
 boundary="----=_Part_123944_1583561974.1531418072190"

------=_Part_123944_1583561974.1531418072190
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 12:51:42 PM UTC-4, Nicol Bolas wrote:
>
> It should be based on TriviallyCopyable, not Trivial. As I understand it,
> that's how it works in MSVC's standard library.
>
>
Agreed: With something like std::copy specifically, using TriviallyCopyable
to choose __builtin_memmove is fine, provided that it also requires that T
is Assignable (i.e. As long as std::copy with a TriviallyCopyable but
Non-assignable T fails to compile.).

libc++ just uses IsTriviallyCopyAssignable to select __builtin_memmove,
which covers the above.

Glen

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/63a462b9-6f91-44ac-98eb-9b6c67380950%40isocpp.org.

------=_Part_123944_1583561974.1531418072190
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 12:51:42 PM UTC-4, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
>It should be based on TriviallyCopyable, not Trivial. As I understand it, =
that&#39;s how it works in MSVC&#39;s standard library.=C2=A0</div><div><br=
></div></div></blockquote><div><br></div><div>Agreed: With something like s=
td::copy specifically, using TriviallyCopyable to choose __builtin_memmove =
is fine, provided that it also requires that T is Assignable (i.e. As long =
as std::copy with a TriviallyCopyable but Non-assignable T fails to compile=
..).</div><div><br></div><div>libc++ just uses IsTriviallyCopyAssignable to =
select __builtin_memmove, which covers the above.</div><div><br></div><div>=
Glen</div><div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/63a462b9-6f91-44ac-98eb-9b6c67380950%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/63a462b9-6f91-44ac-98eb-9b6c67380950=
%40isocpp.org</a>.<br />

------=_Part_123944_1583561974.1531418072190--

------=_Part_123943_2033431296.1531418072190--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 12 Jul 2018 11:30:18 -0700 (PDT)
Raw View
------=_Part_38235_1676582737.1531420218992
Content-Type: multipart/alternative;
 boundary="----=_Part_38236_765713240.1531420218992"

------=_Part_38236_765713240.1531420218992
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 1:54:32 PM UTC-4, Glen Fernandes wrote:
>
> On Thursday, July 12, 2018 at 12:51:42 PM UTC-4, Nicol Bolas wrote:
>>
>> It should be based on TriviallyCopyable, not Trivial. As I understand it,
>> that's how it works in MSVC's standard library.
>>
>>
> Agreed: With something like std::copy specifically, using
> TriviallyCopyable to choose __builtin_memmove is fine, provided that it
> also requires that T is Assignable (i.e. As long as std::copy with a
> TriviallyCopyable but Non-assignable T fails to compile.).
>
> libc++ just uses IsTriviallyCopyAssignable to select __builtin_memmove,
> which covers the above.
>

Actually, it doesn't. `is_trivially_copy_assignable` is a weaker
requirement than `is_trivially_copyable`. The former asks only if the copy
assignment operator is trivial. But that's not sufficient to allow bytewise
copies to work; the standard is very clear on this. To do a bytewise
assignment, you need TriviallyCopyable *as well*.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9f223071-ccdb-49ce-9144-cd66236c0cb8%40isocpp.org.

------=_Part_38236_765713240.1531420218992
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 1:54:32 PM UTC-4, Glen Ferna=
ndes wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On=
 Thursday, July 12, 2018 at 12:51:42 PM UTC-4, Nicol Bolas wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
 #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>It should be based on T=
riviallyCopyable, not Trivial. As I understand it, that&#39;s how it works =
in MSVC&#39;s standard library.=C2=A0</div><div><br></div></div></blockquot=
e><div><br></div><div>Agreed: With something like std::copy specifically, u=
sing TriviallyCopyable to choose __builtin_memmove is fine, provided that i=
t also requires that T is Assignable (i.e. As long as std::copy with a Triv=
iallyCopyable but Non-assignable T fails to compile.).</div><div><br></div>=
<div>libc++ just uses IsTriviallyCopyAssignable to select __builtin_memmove=
, which covers the above.</div></div></blockquote><div><br></div><div>Actua=
lly, it doesn&#39;t. `is_trivially_copy_assignable` is a weaker requirement=
 than `is_trivially_copyable`. The former asks only if the copy assignment =
operator is trivial. But that&#39;s not sufficient to allow bytewise copies=
 to work; the standard is very clear on this. To do a bytewise assignment, =
you need TriviallyCopyable <i>as well</i>.</div><br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9f223071-ccdb-49ce-9144-cd66236c0cb8%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9f223071-ccdb-49ce-9144-cd66236c0cb8=
%40isocpp.org</a>.<br />

------=_Part_38236_765713240.1531420218992--

------=_Part_38235_1676582737.1531420218992--

.


Author: Andrew Schepler <aschepler@gmail.com>
Date: Thu, 12 Jul 2018 16:31:42 -0700 (PDT)
Raw View
------=_Part_72257_23020953.1531438302390
Content-Type: multipart/alternative;
 boundary="----=_Part_72258_865635213.1531438302391"

------=_Part_72258_865635213.1531438302391
Content-Type: text/plain; charset="UTF-8"

I don't agree that the key workaround is just as easy as the allocator
one.  The key way gets rather messy when you want the ability to copy the
object and/or for the class to be a polymorphic base class.  If we want
both, things start looking like this:

class SharedBase
    : public std::enable_shared_from_this<SharedBase>
{
protected:
    class CtorKey {
         CtorKey() = default;
         friend SharedBase;
    };

public:
    SharedBase(const SharedBase&) = delete;
    SharedBase& operator=(const SharedBase&) = delete;
    virtual ~SharedBase() = default;

    template <typename... Arg>
    static auto create(Arg&& ... arg)
        -> std::enable_if_t<std::is_constructible_v<SharedBase, CtorKey, Arg
....>,
            std::shared_ptr<SharedBase>>
    { return std::make_shared<SharedBase>(ctor_key(), std::forward<Arg>(arg
)...); }

    virtual std::shared_ptr<SharedBase> clone() const
    { return create(*this); }

    // Effectively protected:
    explicit SharedBase(CtorKey) : m_a(), m_b(0) {}
    SharedBase(CtorKey, const SharedBase& src) : m_a(src.m_a), m_b(src.m_b)
{}
    SharedBase(CtorKey, std::string a, int b=0) : m_a(std::move(a)), m_b(b)
{}

protected:
    static CtorKey ctor_key() { return {}; }

private:
    std::string m_a;
    int m_b;
};

class SharedDerived final
    : public SharedBase
{
public:
    template <typename... Arg>
    static auto create(Arg&& ... arg)
        -> std::enable_if_t<std::is_constructible_v<SharedDerived, CtorKey,
Arg...>,
            std::shared_ptr<SharedDerived>>
    { return std::make_shared<SharedDerived>(ctor_key(), std::forward<Arg>(
arg)...); }

    std::shared_ptr<SharedBase> clone() const override
    { return create(*this); }

    // Effectively private (?):
    explicit SharedDerived(CtorKey key) : SharedBase(key), m_c(), m_d(0) {}
    SharedDerived(CtorKey key, std::string a, int b, std::string c, int d)
        : SharedBase(key, std::move(a), b), m_c(std::move(c)), m_d(d) {}

private:
    std::string m_c;
    int m_d;
};

In any use of the key pattern, there's extra implementation details
appearing in a "public" section, which could be confusing to someone who
just wants to use the class, and will also show up when using Doxygen or
similar tools.  If we want a copyable class with several members, we must
write a pseudo copy constructor and get all the member copies right - we
can't use "= default".  If we want to allow derived classes, each derived
class needs to duplicate the key logic, meaning the author needs to
somewhat understand it; in my opinion the key pattern is somewhat less
obvious than the allocator pattern.  And then we're counting on authors of
derived classes not to misuse the key to incorrectly create base, derived,
or even objects of other derived types, or to break the key type's
encapsulation.

So I like the allocator pattern better than the key pattern. It might have
its own small cost if an implementation uses extra memory to store a copy
of the allocator but avoids that when using make_shared. But it looks like
at least the g++ library uses the empty base optimization whenever the
allocator type is empty and not final, and so there would be no extra
memory use with Glen's SharedClass::A example.

The friend proposal would make things even simpler than the allocator
pattern, but I'm pretty satisfied with just recommending the allocator
pattern for this sort of problem.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3ed24b06-9612-4d29-96e0-419503bb3156%40isocpp.org.

------=_Part_72258_865635213.1531438302391
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I don&#39;t agree that the key workaround is just as easy =
as the allocator one.=C2=A0 The key way gets rather messy when you want the=
 ability to copy the object and/or for the class to be a polymorphic base c=
lass.=C2=A0 If we want both, things start looking like this:<div><br></div>=
<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); b=
order-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; wo=
rd-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettypr=
int"><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">SharedBase</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">public</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">enable_shared_from_this</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">SharedBase</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">protected</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>class</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">CtorKey</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ctor=
Key</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">default</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">friend</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">SharedBase</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">public</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">SharedBase</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>SharedBase</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&amp;)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">delete</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">SharedBase</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">operator</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">=3D(</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">SharedBase</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&amp;)</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">delete</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">virtual</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">~</span><span style=3D"color: #606;" cla=
ss=3D"styled-by-prettify">SharedBase</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">default=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">templa=
te</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Arg</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">static</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> create</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ar=
g</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">...</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> arg</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">enable_if_t</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">is_constructible_v</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D=
"styled-by-prettify">SharedBase</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">CtorKey</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #606;" class=3D"styled-by-prettify">Arg</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">...&gt;,</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">shared_ptr</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
SharedBase</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&gt;&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">make_shared</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">SharedBase</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify">ctor_key</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(),</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">forward</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-pre=
ttify">Arg</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&gt;(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">arg</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">)...);</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">virtual</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">shared_ptr</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;"=
 class=3D"styled-by-prettify">SharedBase</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> clone</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> create</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(*</span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">this</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" c=
lass=3D"styled-by-prettify">// Effectively protected:</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">explicit</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #606;" class=3D"styled-by-prettify">SharedBase</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">CtorKey</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> m_a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(),</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_b</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D=
"styled-by-prettify">SharedBase</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">CtorKey</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #606;" class=3D"styled-by-prettify">SharedBase</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> src</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> m_a</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
src</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">m_a</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">),</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> m_b</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">src</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">m_b</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">SharedBase=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">CtorKey</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">string</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span=
 style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> m_a</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">move</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">a</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">)),</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> m_b</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">b</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">protected</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">static</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">CtorKey</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> ctor_key</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">{};</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">private</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 std</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">string</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> m_a</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> m_b</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #606;" class=3D"styled-by-prettify">SharedDerived</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">final</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">public</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">SharedBase</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">public</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">Arg</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">static</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> cre=
ate</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">Arg</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> arg</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">-&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">enable_if_t</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">is_constructible_v</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">SharedDerived</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #606;" class=3D"styled-by-prettify">CtorKey</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Arg</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">...&gt;,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">shar=
ed_ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;=
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">SharedDeri=
ved</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;&gt=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">make_shared</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #=
606;" class=3D"styled-by-prettify">SharedDerived</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">ctor_key</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(),</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">forward</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>Arg</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">arg</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">)...);</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 std</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">shared_ptr</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: =
#606;" class=3D"styled-by-prettify">SharedBase</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> clone</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">overr=
ide</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> create</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(*</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">this</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// Effectively private (?):</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">explicit</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">SharedDerived</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606=
;" class=3D"styled-by-prettify">CtorKey</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> key</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">SharedBase</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">key</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">),</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> m_c</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(),</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> m_d</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #066;" class=3D"styled-by=
-prettify">0</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">SharedDerived</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
 style=3D"color: #606;" class=3D"styled-by-prettify">CtorKey</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> key</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">string</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">string</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> c</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">in=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> d</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">SharedBase</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">key</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">move</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">),</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">),</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> m_c</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">move</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>c</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)),</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_d</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">d</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">private</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>string</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_=
c</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> m_d</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">};</span></div></code></div><div><br><=
/div><div>In any use of the key pattern, there&#39;s extra implementation d=
etails appearing in a &quot;public&quot; section, which could be confusing =
to someone who just wants to use the class, and will also show up when usin=
g Doxygen or similar tools.=C2=A0 If we want a copyable class with several =
members, we must write a pseudo copy constructor and get all the member cop=
ies right - we can&#39;t use &quot;=3D default&quot;.=C2=A0 If we want to a=
llow derived classes, each derived class needs to duplicate the key logic, =
meaning the author needs to somewhat understand it; in my opinion the key p=
attern is somewhat less obvious than the allocator pattern.=C2=A0 And then =
we&#39;re counting on authors of derived classes not to misuse the key to i=
ncorrectly create base, derived, or even objects of other derived types, or=
 to break the key type&#39;s encapsulation.</div><div><br></div><div>So I l=
ike the allocator pattern better than the key pattern. It might have its ow=
n small cost if an implementation uses extra memory to store a copy of the =
allocator but avoids that when using make_shared. But it looks like at leas=
t the g++ library uses the empty base optimization whenever the allocator t=
ype is empty and not final, and so there would be no extra memory use with =
Glen&#39;s SharedClass::A example.</div><div><br></div><div>The friend prop=
osal would make things even simpler than the allocator pattern, but I&#39;m=
 pretty satisfied with just recommending the allocator pattern for this sor=
t of problem.</div><div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3ed24b06-9612-4d29-96e0-419503bb3156%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3ed24b06-9612-4d29-96e0-419503bb3156=
%40isocpp.org</a>.<br />

------=_Part_72258_865635213.1531438302391--

------=_Part_72257_23020953.1531438302390--

.


Author: Andrew Schepler <aschepler@gmail.com>
Date: Thu, 12 Jul 2018 16:36:38 -0700 (PDT)
Raw View
------=_Part_112475_1138520390.1531438598149
Content-Type: multipart/alternative;
 boundary="----=_Part_112476_524392807.1531438598149"

------=_Part_112476_524392807.1531438598149
Content-Type: text/plain; charset="UTF-8"

And see, I even forgot the pseudo copy constructor SharedDerived(CtorKey,
const SharedDerived&);

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3853395d-d4f1-4e58-8a44-6f858c13efa6%40isocpp.org.

------=_Part_112476_524392807.1531438598149
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">And see, I even forgot the pseudo copy constructor SharedD=
erived(CtorKey, const SharedDerived&amp;);</div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3853395d-d4f1-4e58-8a44-6f858c13efa6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3853395d-d4f1-4e58-8a44-6f858c13efa6=
%40isocpp.org</a>.<br />

------=_Part_112476_524392807.1531438598149--

------=_Part_112475_1138520390.1531438598149--

.


Author: Glen Fernandes <glen.fernandes@gmail.com>
Date: Thu, 12 Jul 2018 18:38:56 -0700 (PDT)
Raw View
------=_Part_59979_1049655626.1531445936918
Content-Type: multipart/alternative;
 boundary="----=_Part_59980_56684829.1531445936918"

------=_Part_59980_56684829.1531445936918
Content-Type: text/plain; charset="UTF-8"

On Thursday, July 12, 2018 at 7:31:42 PM UTC-4, Andrew Schepler wrote:
>
> I don't agree that the key workaround is just as easy as the allocator
> one.  The key way gets rather messy when you want the ability to copy the
> object and/or for the class to be a polymorphic base class.  If we want
> both, things start looking like this:
>
[...]

> So I like the allocator pattern better than the key pattern.
>
[...]

> The friend proposal would make things even simpler than the allocator
> pattern, but I'm pretty satisfied with just recommending the allocator
> pattern for this sort of problem.
>

You're not alone. While I have no strong preference, I do remember that
private constructors with make_shared was one of smaller the motivating
reasons for supporting LWG 2070 (i.e. allocate_shared using Allocator
construct for construction).

We finally resolved[1] LWG 2070 with our P0674R1 paper, so that behavior is
in for C++2a but library implementations already support it today.

(We had already implemented[2] it in Boost in 2014; Boost 1.58 shipped with
a boost::allocate_shared that supported the above behavior).

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0674r1.html
[2]
https://www.boost.org/doc/libs/1_67_0/libs/smart_ptr/doc/html/smart_ptr.html#history

Glen

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9d105e1e-0a81-459c-b9a0-d6fca3c67219%40isocpp.org.

------=_Part_59980_56684829.1531445936918
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 12, 2018 at 7:31:42 PM UTC-4, Andrew Sch=
epler wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I=
 don&#39;t agree that the key workaround is just as easy as the allocator o=
ne.=C2=A0 The key way gets rather messy when you want the ability to copy t=
he object and/or for the class to be a polymorphic base class.=C2=A0 If we =
want both, things start looking like this:</div></blockquote><div>[...] <br=
></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">So I l=
ike the allocator pattern better than the key pattern. </div></blockquote><=
div>[...] <br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div></div><div>The friend proposal would make things even simpler=
 than the allocator pattern, but I&#39;m pretty satisfied with just recomme=
nding the allocator pattern for this sort of problem.</div></div></blockquo=
te><div><br></div><div>You&#39;re not alone. While I have no strong prefere=
nce, I do remember that private constructors with make_shared was one of sm=
aller the motivating reasons for supporting LWG 2070 (i.e. allocate_shared =
using Allocator construct for construction).</div><div><br></div><div>We fi=
nally resolved[1] LWG 2070 with our P0674R1 paper, so that behavior is in f=
or C++2a but library implementations already support it today.</div><div><b=
r></div><div>(We had already implemented[2] it in Boost in 2014; Boost 1.58=
 shipped with a boost::allocate_shared that supported the above behavior).<=
/div><br><div>[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p=
0674r1.html<br></div><div>[2] https://www.boost.org/doc/libs/1_67_0/libs/sm=
art_ptr/doc/html/smart_ptr.html#history</div><div><br></div><div>Glen<br></=
div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9d105e1e-0a81-459c-b9a0-d6fca3c67219%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9d105e1e-0a81-459c-b9a0-d6fca3c67219=
%40isocpp.org</a>.<br />

------=_Part_59980_56684829.1531445936918--

------=_Part_59979_1049655626.1531445936918--

.


Author: Boris Dalstein <dalboris@gmail.com>
Date: Sun, 15 Jul 2018 14:49:49 +0200
Raw View
Thanks a lot Glen for the idea of using std::allocate_shared instead of
std::make_shared! After a bit of experimenting, I do find it to be my
preferred workaround, for the same reasons highlighted by Andrew.

Yet, I still think that the proposed std::shared_ptr_access would be
much cleaner. In my opinion, the current need to use this allocator
pattern (or alternatives) is one of the few annoyances which still makes
using shared_ptr a pain compared to raw pointers or custom-made smart
pointers, in many common idioms. In fact, this issue alone makes me
consider switching my whole project from using shared_ptr to using
custom intrusive reference counting smart pointers, a tempting
alternative which I've been trying hard to resist so far ("keep it
simple", etc.). Ideally, I do think the C++ landscape is better off if
most libraries use standard smart pointers instead of custom-made ones,
and I believe that additional facilities such as the proposed
std::shared_ptr_access, by elegantly solving one of the well-known
limitations of make_shared, makes this ideal landscape more likely to
happen.

If it makes sense to other people, and if a C++ expert is available to
guide me a little (I'm far from a C++ expert myself), I would be more
than willing to spend the time writing an actual proposal for this.

- Boris

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/34c9a2b3-f8f2-b565-21f6-6056c21b4374%40gmail.com.

.


Author: bhassink@gmail.com
Date: Sat, 17 Nov 2018 22:40:27 -0800 (PST)
Raw View
------=_Part_1745_1093368363.1542523227878
Content-Type: multipart/alternative;
 boundary="----=_Part_1746_2089407853.1542523227878"

------=_Part_1746_2089407853.1542523227878
Content-Type: text/plain; charset="UTF-8"

When the internal wrapper involves inheritance, it prevents the use of the
"final" specifier on the wrapped class.

Per an answer in the stack overflow threaded noted earlier, there's a way
to do this using the shared pointer aliasing ctor.  Unfortunately, the
complete solution also requires rolling an equivalent of
std::enable_shared_from_this because the initial shared pointer is to an
internal wrapper instead of the member type.

-B

On Thursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Fernandes wrote:
>
> I wrote:
>>
>> e.g. Using his SharedClass example above, this works for the create()
>> function:
>>
>>
> I remembered how we actually specified things in P0674R1, so the following
> is probably a better example instead:
>
> class SharedClass {
> public:
>     static std::shared_ptr<SharedClass> create()
>     { return std::allocate_shared<SharedClass>(A<SharedClass>()); }
> private:
>     template<class T> struct A : std::allocator<T> {
>         void construct(void* p) { ::new(p) SharedClass(); }
>         void destroy(SharedClass* p) { p->~SharedClass(); }
>     };
>     SharedClass() = default;
>     ~SharedClass() = default;
> };
>
> i.e. We mandated rebind before construct.
>
> In any case, not many lines of code to achieve the same thing (private
> constructors, single allocation shared_ptr).
>
> Glen
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/57859fb0-8a2b-41b7-8406-c611f74c222b%40isocpp.org.

------=_Part_1746_2089407853.1542523227878
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>When the internal wrapper involves inheritance, it pr=
events the use of the &quot;final&quot; specifier on the wrapped class.</di=
v><div><br></div><div>Per an answer in the stack overflow threaded noted ea=
rlier, there&#39;s a way to do this using the shared pointer aliasing ctor.=
=C2=A0 Unfortunately, the complete solution also requires rolling an equiva=
lent of std::enable_shared_from_this because the initial shared pointer is =
to an internal wrapper instead of the member type.</div><div><br></div><div=
>-B<br></div><br>On Thursday, July 12, 2018 at 9:41:58 AM UTC-4, Glen Ferna=
ndes wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>e.g. Us=
ing his SharedClass example above, this works for the create() function:<br=
></div><div><br></div></div></blockquote><div><br></div><div>I remembered h=
ow we actually specified things in P0674R1, so the following is probably a =
better example instead:=C2=A0</div><div>=C2=A0</div><div><div>class SharedC=
lass {</div><div>public:</div><div>=C2=A0 =C2=A0 static std::shared_ptr&lt;=
SharedClass&gt; create()</div><div>=C2=A0 =C2=A0 { return std::allocate_sha=
red&lt;<wbr>SharedClass&gt;(A&lt;SharedClass&gt;())<wbr>; }</div><div>priva=
te:</div><div>=C2=A0 =C2=A0 template&lt;class T&gt; struct A : std::allocat=
or&lt;T&gt; {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 void construct(void* p)=
 { ::new(p) SharedClass(); }</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 void des=
troy(SharedClass* p) { p-&gt;~SharedClass(); }</div><div>=C2=A0 =C2=A0 };</=
div><div>=C2=A0 =C2=A0 SharedClass() =3D default;</div><div>=C2=A0 =C2=A0 ~=
SharedClass() =3D default;</div><div>};</div></div><div><br></div><div>i.e.=
 We mandated rebind before construct.=C2=A0</div><div><br></div><div>In any=
 case, not many lines of code to achieve the same thing (private constructo=
rs, single allocation shared_ptr).</div><div><br></div><div>Glen</div></div=
></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/57859fb0-8a2b-41b7-8406-c611f74c222b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/57859fb0-8a2b-41b7-8406-c611f74c222b=
%40isocpp.org</a>.<br />

------=_Part_1746_2089407853.1542523227878--

------=_Part_1745_1093368363.1542523227878--

.