Boost C++ Libraries: Ticket #5381: get_deleter<D>(ptr) needs D to be exactly known https://svn.boost.org/trac10/ticket/5381 <p> get_deleter&lt;Base_of_D&gt;(ptr) returns 0. </p> <p> This makes efficient polymorphous COW pointer implementations internally based on shared_pointer inefficient, because it is not possible to have reference count (deleter) and pointee allocated in one memory block, as is done in boost:::make_shared. Note, COW pointer need access to the deleter for the clone function at a time later than the constructor. </p> <p> Suggestion: either supply: </p> <p> template &lt;typename T, D&gt; void const * get_deleter_raw(shared_ptr&lt;T&gt; const &amp; ptr); </p> <p> or implement </p> <p> Base_of_D const * get_deleter&lt;Base_of_D&gt;(shared_ptr&lt;T&gt; const &amp; ptr) </p> <p> returning pointer to ptrs deleter of type D (using dynamic_cast?) if B is a virtual class, (maybe using trait has_virtual_destructor) </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/5381 Trac 1.4.3 Steven Watanabe Wed, 06 Apr 2011 21:32:50 GMT <link>https://svn.boost.org/trac10/ticket/5381#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5381#comment:1</guid> <description> <p> Replying to <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5381" title="#5381: Feature Requests: get_deleter&lt;D&gt;(ptr) needs D to be exactly known (closed: wontfix)">christian.kotz@…</a>: </p> <blockquote class="citation"> <p> get_deleter&lt;Base_of_D&gt;(ptr) returns 0. </p> <p> This makes efficient polymorphous COW pointer implementations internally based on shared_pointer inefficient, because it is not possible to have reference count (deleter) and pointee allocated in one memory block, as is done in boost:::make_shared. Note, COW pointer need access to the deleter for the clone function at a time later than the constructor. </p> </blockquote> <p> I don't understand. If you want to make something like make_shared, you should only need to access the deleter when you're constructing the object. At this point, you need to know the exact type of the deleter anyway. Actually, though, I don't see what you want to do that can't be handled by just using make_shared. </p> </description> <category>Ticket</category> </item> <item> <author>christian.kotz@…</author> <pubDate>Thu, 07 Apr 2011 18:25:42 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5381#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5381#comment:2</guid> <description> <p> For a copy on write pointer it is not sufficient to use the actual type in the constructor only, where it is known, a la make_shared. On dereference (not construction time) it may be necessary to lazily clone (create a copy) of the pointee. In this case splicing must be avoided, so even if we have a shared_ptr&lt;Base&gt; which has been constructed from a make_shared&lt;Derived&gt; invokation the actual pointee carrier must be cloned (Derived not Base!). </p> <p> here some code fragments, which sketch the "deleter" </p> <p> class Carrier_base { </p> <p> ... most omitted private: </p> <blockquote> <p> virtual Carrier_base *clone() = 0; </p> </blockquote> <p> }; </p> <p> template &lt;typename T, typename A = ::std::allocator&lt;T&gt; &gt; class Carrier : </p> <blockquote> <p> private A::template rebind&lt;T&gt;::other </p> </blockquote> <p> { ... most ommitted </p> <blockquote> <p> typedef typename A::template rebind&lt;T&gt;::other allocator_type; </p> </blockquote> <blockquote> <p> template &lt;typename Other_A, typename... Args&gt; static Carrier&lt;T,A&gt; * create(Other_A allocator, Args... args); </p> </blockquote> <blockquote> <p> T * address() const; </p> </blockquote> <p> private: </p> <blockquote> <p> template &lt;typename Other_A, typename... Args&gt; explicit Carrier(Other_A allocator, Args... args); </p> </blockquote> <blockquote> <p> Carrier&lt;T,A&gt; * clone() const{ <em> override </em></p> <blockquote> <p> Carrier&lt;T,A&gt; * result = allocate(1,0); try { </p> <blockquote> <p> new (allocator_type(*this)) Carrier&lt;T,A&gt;(*this); </p> </blockquote> <p> } catch(...) { </p> <blockquote> <p> deallocate(result); throw; </p> </blockquote> <p> } return result; </p> </blockquote> <p> } </p> </blockquote> <p> }; </p> <p> If I only allow construction in a make_shared like fashion, I know on clone time that only a class derived from Carrier_base can be the deleter. This is sufficient to invoke cloning. The actual Carrier&lt;X&gt; need not and cannot be in general be known. Note COW pointer is not a ::boost::shared_ptr but privatrely inherits from one or has a private member. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Thu, 07 Apr 2011 18:42:47 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5381#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5381#comment:3</guid> <description> <p> A solution could be to expose some internals to derived classes of ::boost::shared_ptr via protected, not private access control. This will on one side not endanger usage of shared_ptr, while giving implementations based on shared_ptr access (implementation is inherited via non public, e.g. private inheritance). </p> </description> <category>Ticket</category> </item> <item> <author>christian.kotz@…</author> <pubDate>Thu, 07 Apr 2011 18:50:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5381#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5381#comment:4</guid> <description> <p> remark: Carrier&lt;T,A&gt; has the same function for the COW_ptr as boost::details::sp_ms_deleter in boost::make_shared </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Peter Dimov</dc:creator> <pubDate>Fri, 13 Dec 2013 22:35:19 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/5381#comment:5 https://svn.boost.org/trac10/ticket/5381#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> Given its age, this ticket is probably no longer relevant. Still, there is now an undocumented accessor, <code>void * _internal_get_untyped_deleter() const</code>, which can be used. It's not very likely to be provided as part of the public interface though. </p> Ticket