Boost C++ Libraries: Ticket #3996: Enable use of BOOST_FOREACH over const-ref of noncopyable ptr_containers https://svn.boost.org/trac10/ticket/3996 <p> I have encountered an error about allocating abstract type, with the following code: </p> <pre class="wiki">#include "boost/ptr_container/ptr_vector.hpp" #include "boost/foreach.hpp" struct S { virtual void f() const = 0; }; typedef boost::ptr_vector&lt;S&gt; ptr_vector; void f(ptr_vector const&amp; v) { BOOST_FOREACH(S const&amp; s, v) s.f(); } </pre><p> And I found this is a known issue: <a href="http://www.boost.org/doc/libs/1_42_0/doc/html/foreach/extensibility.html#id862475">Boost.Foreach &gt; Extensibility</a> </p> <p> Then I thought that boost::foreach::is_noncopyable&lt;&gt; should be specialized for ptr_containers of which value_type is abstruct. Then I put the following: </p> <pre class="wiki">namespace boost { namespace foreach { template&lt;typename T, typename A, typenale CA&gt; struct is_noncopyable&lt;ptr_vector&lt;T,A,CA&gt; &gt; : is_abstract&lt;T&gt; {}; }} </pre><p> ... and the error disappeared. </p> <p> After that, since ptr_container is designed to be an alternative of the standard containers for the case of the value is non-copyable, I thought this is a wide problem worth making a patch. </p> <p> The patch looks better than the above workaround in some points: </p> <ul><li>fixes the problem for all ptr_containers at once </li><li>also supports types marked by boost::noncopyable </li><li>keeps the container copyable if view_clone_allocator is used </li></ul><p> The patch also includes some test cases I actually used, while I have no idea how to integrate it into boost test infrastructure. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3996 Trac 1.4.3 Kazutoshi Satoda <k_satoda@…> Wed, 10 Mar 2010 20:25:40 GMT attachment set https://svn.boost.org/trac10/ticket/3996 https://svn.boost.org/trac10/ticket/3996 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">ptr_container_propagate_noncopyable_for_foreach.patch</span> </li> </ul> <p> The fix and test cases </p> Ticket Kazutoshi Satoda <k_satoda@…> Thu, 11 Mar 2010 15:29:49 GMT attachment set https://svn.boost.org/trac10/ticket/3996 https://svn.boost.org/trac10/ticket/3996 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">foreach_separate_headers_for_extensibility.patch</span> </li> </ul> <p> svn diff for trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/60445" title="m">r60445</a> </p> Ticket Kazutoshi Satoda <k_satoda@…> Thu, 11 Mar 2010 15:32:41 GMT attachment set https://svn.boost.org/trac10/ticket/3996 https://svn.boost.org/trac10/ticket/3996 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">foreach_separate_headers_for_extensibility.2.patch</span> </li> </ul> <p> svn diff for trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/60445" title="m">r60445</a> </p> Ticket Kazutoshi Satoda <k_satoda@…> Thu, 11 Mar 2010 15:33:47 GMT attachment set https://svn.boost.org/trac10/ticket/3996 https://svn.boost.org/trac10/ticket/3996 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">ptr_container_propagate_noncopyable_for_foreach.2.patch</span> </li> </ul> <p> svn diff for trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/60445" title="m">r60445</a> </p> Ticket Kazutoshi Satoda <k_satoda@…> Thu, 11 Mar 2010 15:39:06 GMT <link>https://svn.boost.org/trac10/ticket/3996#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3996#comment:1</guid> <description> <p> Sorry but, the first patch broke all tests which doesn't include boost/foreach.hpp. </p> <p> Now I attached a new patch. The new one depends on another patch submitted as ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3998" title="#3998: Patches: Provide light weight headers for extensibility features of BOOST_FOREACH (closed: wontfix)">#3998</a>. </p> <p> ... sorry again, I did mistakes attaching a patch. Please remove two wrong patches (foreach_....patch, they are for <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3998" title="#3998: Patches: Provide light weight headers for extensibility features of BOOST_FOREACH (closed: wontfix)">#3998</a>), and the first patch. I seem not having the permission to do that by myself. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Thu, 24 Jun 2010 22:17:58 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3996#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3996#comment:2</guid> <description> <p> Do NOT accept this patch. For every instantiation of reversible_ptr_container, you are instantiating foreach::is_noncopyable to (optionally) inherit from noncopyable. This is the wrong way to do it and will lead to ODR violations when different translation units see different specializations of foreach::is_noncopyable. Instead, define a partial specialization of foreach::is_noncopyable&lt; reversible_ptr_container&lt;...&gt; &gt;: </p> <pre class="wiki">namespace boost { namespace foreach { template&lt;typename T, typename A, typenale CA&gt; struct is_noncopyable&lt;ptr_vector&lt;T,A,CA&gt; &gt; : is_noncopyable&lt;T&gt; {}; }} </pre> </description> <category>Ticket</category> </item> <item> <author>Kazutoshi Satoda <k_satoda@…></author> <pubDate>Fri, 25 Jun 2010 00:20:40 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3996#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3996#comment:3</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3996#comment:2" title="Comment 2">eric_niebler</a>: </p> <blockquote class="citation"> <p> ... and will lead to ODR violations when different translation units see different specializations of foreach::is_noncopyable. </p> </blockquote> <p> How different specializations of foreach::is_noncopyable&lt;&gt; can be seen for a ValueType which is required to be complete for the instantiation of foreach::is_noncopyable&lt;ValueType&gt; in my patch? </p> <p> I can imagine a case where the specialization of foreach::is_noncopyable&lt;ValueType&gt; is provided in a separate header from one which defines ValueType. But in such case, the problem is in ValueType; the same problem can be caused without my patch. </p> <blockquote class="citation"> <p> Instead, define a partial specialization of foreach::is_noncopyable&lt; reversible_ptr_container&lt;...&gt; &gt; </p> </blockquote> <p> Providing a specialization of foreach::is_noncopyable&lt;&gt; for a base class isn't propagated to derived classes (ptr_vector&lt;...&gt;, ptr_list&lt;...&gt;, ... in this case). With that approach, duplicated definitions of specialization would be required. I think it's hardly acceptable, especially thinking users can define their own ptr_container using reversible_ptr_container&lt;&gt;. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Eric Niebler</dc:creator> <pubDate>Fri, 25 Jun 2010 01:03:28 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3996#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3996#comment:4</guid> <description> <p> 1) A type ThirdParty is defined in ThirdParty.h. The user can't edit this file because it's not hers. It does not specialize is_noncopyable because it knows nothing about BOOST_FOREACH. </p> <p> 2) A user creates her own ThirdPartyForEach.h that #includes ThirdParty.h and specializes is_noncopyable. Where ever she wants to use ThirdParty together with BOOST_FOREACH, she includes ThirdPartyForEach.h </p> <p> 3) In Unit1.cpp, the user instantiates ptr_vector&lt;ThirdParty&gt;. She includes ThirdParty.h instead of ThirdPartyForEach.h because in this translation unit she is not using BOOST_FOREACH. </p> <p> 4) In Unit2.cpp, she also instantiates ptr_vector&lt;ThirdParty&gt;. She *does* include ThirdPartyForEach.h in this translation unit because it uses BOOST_FOREACH. </p> <p> 5) Undefined behavior. </p> <p> The problem stems from the fact that the user cannot possibly know that she needs to include ThirdPartyForEach.h EVEN IN TRANSLATION UNITS THAT DON'T USE BOOST_FOREACH. This is a recipe for ODR violations. </p> <p> Contrast this with my suggested solution. is_noncopyable will *only* be instantiated in the translation units that actually use BOOST_FOREACH. In these source files, it's natural to expect people to include the header that correctly implements the foreach hooks. </p> </description> <category>Ticket</category> </item> <item> <author>Kazutoshi Satoda <k_satoda@…></author> <pubDate>Sat, 26 Jun 2010 04:07:54 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3996#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3996#comment:5</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3996#comment:4" title="Comment 4">eric_niebler</a>: Thank you for the clarification. Now I agree. I'll try to make another patch. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sat, 11 Dec 2010 14:20:57 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3996#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3996#comment:6</guid> <description> <p> Is there any news about this issue? I have encountered it myself today and I think, I will rather not use BOOST_FOREACH than inserting a workaround somewhere in my project. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Thorsten Ottosen</dc:creator> <pubDate>Thu, 31 Mar 2011 20:24:30 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/3996#comment:7 https://svn.boost.org/trac10/ticket/3996#comment:7 <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">fixed</span> </li> </ul> Ticket Kazutoshi Satoda <k_satoda@…> Sat, 02 Apr 2011 11:06:19 GMT status, version, milestone changed; resolution deleted https://svn.boost.org/trac10/ticket/3996#comment:8 https://svn.boost.org/trac10/ticket/3996#comment:8 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>version</strong> <span class="trac-field-old">Boost 1.42.0</span> → <span class="trac-field-new">Boost Development Trunk</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">fixed</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.43.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3996#comment:7" title="Comment 7">nesotto</a>: I verified that the problem is still not fixed at trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/70851" title="Website: Upddate the site updating page.">r70851</a>. I assume you missed the problem because you tested with a compiler that enables BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION. </p> <p> Now, I made the 3rd patch. This version contains a test which will can show the problem in all compilers, and takes care of ODR violation which Eric Niebler pointed out. </p> <p> Only one test "const_element_containers" fails on my machine (cygwinx86, g++ 4.3.4): </p> <blockquote class="citation"> <p> const_element_containers.cpp:19: error: expected primary-expression before 'template' const_element_containers.cpp:19: error: expected `;' before 'template' ... </p> </blockquote> <p> But I'm assuming this is not caused by my change because it is syntax errors in the test code. </p> Ticket Kazutoshi Satoda <k_satoda@…> Sat, 02 Apr 2011 11:08:41 GMT attachment set https://svn.boost.org/trac10/ticket/3996 https://svn.boost.org/trac10/ticket/3996 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">ptr_container_propagate_noncopyable_for_foreach.3.patch</span> </li> </ul> <p> svn diff for trunk <a class="changeset" href="https://svn.boost.org/trac10/changeset/70851" title="Website: Upddate the site updating page.">r70851</a> </p> Ticket Jonathan Jones <jonathan.jones@…> Fri, 20 Jul 2012 19:32:45 GMT cc set https://svn.boost.org/trac10/ticket/3996#comment:9 https://svn.boost.org/trac10/ticket/3996#comment:9 <ul> <li><strong>cc</strong> <span class="trac-author">jonathan.jones@…</span> added </li> </ul> Ticket