Boost C++ Libraries: Ticket #7100: unorderd_set<shared_ptr<T> > > - insert does not increment count https://svn.boost.org/trac10/ticket/7100 <p> It seems unordered_set::insert has stopped working for shared_ptr's between v 1.48 and now. Consider the following example: </p> <pre class="wiki">#include &lt;iostream&gt; #define USING_BOOST 1 #if USING_LIBCPP #include &lt;unordered_set&gt; #include &lt;memory&gt; #elif USING_BOOST #include "boost/shared_ptr.hpp" #include "boost/unordered_set.hpp" using namespace boost; #endif using namespace std; int main() { unordered_set&lt;shared_ptr&lt;int&gt; &gt; mySet; shared_ptr&lt;int&gt; intSP( new int( 1 ) ); cout &lt;&lt; "use_count A: " &lt;&lt; intSP.use_count() &lt;&lt; endl; mySet.insert( intSP ); cout &lt;&lt; "use_count B: " &lt;&lt; intSP.use_count() &lt;&lt; endl; return 0; } </pre><p> In boost-trunk (and release version 1.50), use_count after the insert is still 1. In boost version 1.48, the use_count is incremented by the insert to 2. This is also the case with libc++. </p> <p> Sorry, I don't know what the results are in 1.49. </p> <p> This was tested clang on Mac OS X: </p> <pre class="wiki">$ clang --version Apple clang version 4.0 (tags/Apple/clang-421.10.48) (based on LLVM 3.1svn) Target: x86_64-apple-darwin11.4.0 Thread model: posix </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7100 Trac 1.4.3 John Maddock Sat, 07 Jul 2012 11:21:37 GMT owner, component changed https://svn.boost.org/trac10/ticket/7100#comment:1 https://svn.boost.org/trac10/ticket/7100#comment:1 <ul> <li><strong>owner</strong> changed from <span class="trac-author">John Maddock</span> to <span class="trac-author">Daniel James</span> </li> <li><strong>component</strong> <span class="trac-field-old">TR1</span> → <span class="trac-field-new">unordered</span> </li> </ul> Ticket Daniel James Sun, 08 Jul 2012 11:55:59 GMT <link>https://svn.boost.org/trac10/ticket/7100#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7100#comment:2</guid> <description> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/79358" title="Unordered: Fix using a C++03 allocator with C++11 compiler. Because ...">[79358]</a>) Unordered: Fix using a C++03 allocator with C++11 compiler. </p> <p> Because the nodes had an implicit constructor, the <code>has_construct</code> traits was detecting that the nodes could be constructed by construction then copy, which really wasn't wanted. Also add a check that nodes aren't been copy constructed to make sure this doesn't happen again. Refs <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7100" title="#7100: Bugs: unorderd_set&lt;shared_ptr&lt;T&gt; &gt; &gt; - insert does not increment count (closed: fixed)">#7100</a>. </p> </description> <category>Ticket</category> </item> <item> <author>Rich Eakin <reakinator@…></author> <pubDate>Mon, 09 Jul 2012 02:42:59 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/7100 https://svn.boost.org/trac10/ticket/7100 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">clang_error_nomatchingfunction.txt</span> </li> </ul> <p> clang compile error log "No Matching Function.." </p> Ticket Rich Eakin <reakinator@…> Mon, 09 Jul 2012 02:46:50 GMT <link>https://svn.boost.org/trac10/ticket/7100#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7100#comment:3</guid> <description> <p> Thanks for the fix, I can confirm that insert increments the ref count with boost::unordered_set&lt;boost::shared_ptr&lt;T&lt; &gt;. </p> <p> However, I think it has created a problem when using std::tr1::shared_ptr. Albeit an odd setup, the following example produces a compile time error: </p> <pre class="wiki"> #include "boost/unordered_set.hpp" #include &lt;tr1/memory&gt; int main() { boost::unordered_set&lt;std::tr1::shared_ptr&lt;int&gt; &gt; mySet; std::tr1::shared_ptr&lt;int&gt; intSP( new int( 1 ) ); mySet.insert( intSP ); // &lt;-- Error: (Semantic Issue) "no matching function for call to 'hash_value'" return 0; } </pre><p> I have attached the full error log from clang. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel James</dc:creator> <pubDate>Mon, 09 Jul 2012 11:16:15 GMT</pubDate> <title>status, version, milestone changed https://svn.boost.org/trac10/ticket/7100#comment:4 https://svn.boost.org/trac10/ticket/7100#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> <li><strong>version</strong> <span class="trac-field-old">Boost 1.51.0</span> → <span class="trac-field-new">Boost 1.50.0</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.51.0</span> </li> </ul> <p> I'm afraid that's a feature, not a bug. There's no support for <code>std::shared_ptr</code> or <code>std::tr1::shared_ptr</code>, older versions were accidentally picking up the implicit conversion to <code>bool</code> and hashing based on that - which is really bad as it only returns two possible hash values. So 1.51 is going to prevent that happening. </p> <p> I might add support for <code>std::shared_ptr</code> in a future version, but if you really to use it, the best thing to do is to use a custom hash function, something like (untested): </p> <pre class="wiki">struct hash_shared_ptr { std::size_t operator()(std::tr1::shared_ptr&lt;int&gt; const&amp; x) { boost::hash&lt;int*&gt; hf; return hf(x.get()); } }; </pre><p> If you really need <code>boost::hash</code> to support <code>shared_ptr</code>, then you probably should specialize it. </p> <p> Btw. you probably know this, but when you use a <code>shared_ptr</code> as a set element, it stores it based on the address, not the value it points to. I just thought I should mention it as people sometimes get confused. </p> Ticket Rich Eakin <reakinator@…> Tue, 10 Jul 2012 01:07:08 GMT <link>https://svn.boost.org/trac10/ticket/7100#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7100#comment:5</guid> <description> <p> Ah, right you are! I had forgotten about that and had a bug in my own code. That must mean that std::unordered_set is also using the implicit bool to hash? It is really nice that you can catch it, as it is almost certainly not what was intended. </p> <p> Btw, yes the goal is to map unique objects based on their address. Thank you nonetheless for your kind and thorough advice! </p> <p> All is working well now, cheers. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel James</dc:creator> <pubDate>Tue, 10 Jul 2012 07:08:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/7100#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7100#comment:6</guid> <description> <p> No, std::hash is specialized for std::shared_ptr, so I should definitely do the same. It doesn't have this problem, it's an unintended consequence of boost::hash's extensions. I think I'll add support for std::shared_ptr in 1.51, I am lagging behind a bit with C++11 support. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Daniel James</dc:creator> <pubDate>Sun, 15 Jul 2012 23:58:05 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/7100#comment:7 https://svn.boost.org/trac10/ticket/7100#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/79547" title="Unordered: Merge allocator fix + improved tests. Fixes #7100. ">[79547]</a>) Unordered: Merge allocator fix + improved tests. Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/7100" title="#7100: Bugs: unorderd_set&lt;shared_ptr&lt;T&gt; &gt; &gt; - insert does not increment count (closed: fixed)">#7100</a>. </p> Ticket