Boost C++ Libraries: Ticket #9338: VS2005 compiler errors in swap() definition after including container/memory_util.hpp https://svn.boost.org/trac10/ticket/9338 <p> This problem is perfectly reproducable under VS2005 even with the latest boost 1_55 rc. </p> <p> Here's the minimal reproducable example: </p> <p> <em> ----- </em> This was the original inclusion actually <em>#include &lt;boost/container/flat_map.hpp&gt; #include &lt;boost/container/detail/config_begin.hpp&gt; #include &lt;boost/intrusive/detail/memory_util.hpp&gt; #include &lt;boost/container/detail/memory_util.hpp&gt; </em></p> <p> void swap(); <em> ------ </em></p> <p> In VS2005 this innocent piece of code yields: <em> ------ error C2365: 'swap' : redefinition; previous definition was 'formerly unknown identifier' </em> ------ </p> <p> VS2010 and GCC 4.5.2 have no complaints. </p> <p> Looks like VS2005 compiler is entangled somehow by BOOST_INTRUSIVE_HAS_MEMBER magic. Actually, it's quite a headache that with VS2005 one can't introduce swap() after, say, flat_map is included. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9338 Trac 1.4.3 Göran Orsander <goran.orsander.lw@…> Fri, 15 Nov 2013 08:22:38 GMT <link>https://svn.boost.org/trac10/ticket/9338#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9338#comment:1</guid> <description> <p> You get the same problem with VS2008 for both boost 1.54.0 and 1.55.0 </p> <p> I use &lt;boost/container/string.hpp&gt; and it will include both &lt;container/detail/memory_util.hpp&gt; and &lt;intrusive/detail/memory_util.hpp&gt; </p> <p> Another third party library I use also defines 'swap' in the global namespace. This is quite a headache since I cannot modify the code in either boost or the other third party library. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Sat, 16 Nov 2013 21:53:34 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9338#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9338#comment:2</guid> <description> <p> Thanks for the report. I've tried to find a workaround with no luck. It's definitely a bug in the compiler, a really strange one. If your swap function is declared in a namespace the error disappears. The bug is present at least from Visual 2003. </p> <p> The error is triggered from boost/intrusive/detail/has_member_function_callable_with.hpp, which produces (for swap) the code </p> <blockquote> <p> template&lt; class F </p> <blockquote> <p> , std::size_t N = sizeof((boost::move_detail::declval&lt;F&gt;().swap (), 0))&gt; </p> </blockquote> <p> struct zeroarg_checker_swap </p> </blockquote> <p> This ".swap()" call in the sizeof expression to use SFINAE to detect if the expression is correct seems to provoke the error. Sadly, I haven't found any workaround. </p> </description> <category>Ticket</category> </item> <item> <author>Fedor Trushkin <ted-xp@…></author> <pubDate>Sun, 17 Nov 2013 09:43:59 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9338#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9338#comment:3</guid> <description> <p> Could you explain, please, why zero arguments case is handled specially? I modified it to use the same ideas an in funwrap and it seems acting perfectly without any compiler errors. That's how it looks like after preprocessing: </p> <pre class="wiki"> template&lt;typename Fun&gt; struct funwrap0_swap : Fun { funwrap0_swap(); using Fun::swap; boost_intrusive_has_member_function_callable_with::private_type swap() const; }; template&lt;typename Fun&gt; struct has_member_function_callable_with_swap_impl &lt;Fun, true , void &gt; { typedef funwrap0_swap&lt;Fun&gt; FunWrap; static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) == sizeof(boost_intrusive_has_member_function_callable_with::is_private_type ( (boost::move_detail::declval&lt;FunWrap&gt;(). swap(), 0 ) ) ) ); }; </pre><p> For me the only worrying thing is <code>using std::swap</code> statement, as I don't get how exactly should this be regarded by compiler if no swap is available in <code>Fun</code> base class. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Sun, 17 Nov 2013 13:16:49 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9338#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9338#comment:4</guid> <description> <p> If the template argument "Fun" has a member swap defined as: </p> <pre class="wiki"> struct Func { void swap() const {} }; </pre><p> Then the trait would lie and it would tell us that such member does not exist (the wrapper is a derived class that hides the base method). If you replace </p> <pre class="wiki"> boost_intrusive_has_member_function_callable_with::private_type swap() const; </pre><p> with (variadic version) </p> <pre class="wiki"> boost_intrusive_has_member_function_callable_with::private_type swap(...) const; </pre><p> then a compilation error would be triggered as </p> <pre class="wiki"> boost::move_detail::declval&lt;FunWrap&gt;().swap() </pre><p> would be ambiguous (the compiler does not know if the variadic version from the wrapper or the base zero argument version should be called. </p> <p> In non-zero argument cases, a special argument "dont_care" is used generated a very different member overload. If that is selected, then the member does not exist. With 0 arguments, this is not possible. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Sun, 17 Nov 2013 13:20:42 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9338#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9338#comment:5</guid> <description> <p> A workaround is to tweak "boost/intrusive/detail/has_member_function_callable_with.hpp" to support non-zero lower bound values. Until now, are traits are generated from 0 to N arguments, but many of them don't need 0 arguments. "swap" is one of them (we are looking for "T::swap(T&amp;)", no "T::swap()"). This would also generate less preprocessed code. </p> <p> Other member names are likely to be less used in the global namespace than "swap", so let's see if this can at least minimize the compiler bug effects. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Mon, 18 Nov 2013 09:32:45 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9338#comment:6 https://svn.boost.org/trac10/ticket/9338#comment:6 <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> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/86748" title="Fixes #9338">[86748]</a>) Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/9338" title="#9338: Bugs: VS2005 compiler errors in swap() definition after including ... (closed: fixed)">#9338</a> </p> Ticket