Boost C++ Libraries: Ticket #4003: Error in destroy.hpp when methods "T()" and "operator~()" are defined. https://svn.boost.org/trac10/ticket/4003 <p> I am wrapping a large library using boost python and Py++. I encountered a peculiar situation with one of the wrapped classes. </p> <p> I have attached a minimal example and an imperfect patch (see below). </p> <p> The problem occurs on line 33 of boost/python/detail/destroy.hpp: </p> <pre class="wiki">unpatched version: ================= 30 template &lt;class T&gt; 31 static void execute(T const volatile* p) 32 { 33 p-&gt;T::~T(); 34 } </pre><p> The problem is that the class being wrapped has a member function "T()", and the class returned by that function has an "operator~()"; which leads to a compile error. I have been working around this for the past year by patching the file destroy.hpp to use the name "Type" instead of "T" in this section, each time I install a new version of boost. </p> <pre class="wiki">patched version: =============== 30 template &lt;class Type&gt; 31 static void execute(Type const volatile* p) 32 { 33 p-&gt;Type::~Type(); 34 } </pre><p> That's not a complete solution, of course. I suspect I could concoct another scenario with classes that have a "Type" method etc. But it solves the problem for me with the libraries I am actually wrapping. Perhaps you C++ gurus could come up with a more robust approach. </p> <p> With the patch in place, my module compiles. Without the patch, I get these compiler messages: </p> <p> ############################################################# building 'foo_module' extension C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS - /DNDEBUG "-IC:/Program Files/boost/boost_1_42" -I. -Ic:\Python26\include -Ic:\Pytho n26\PC /Tpwrap_foo.cpp /Fobuild\temp.win32-2.6\Release\wrap_foo.obj /EHsc -D"_HAS_TR1 =0" wrap_foo.cpp C:/Program Files/boost/boost_1_42\boost/python/detail/destroy.hpp(33) : error C2523: 'Foo3::~T' : destructor tag mismatch </p> <blockquote> <p> C:/Program Files/boost/boost_1_42\boost/python/detail/destroy.hpp(95) : see reference to function template instantiation 'void boost::python::detail::value_destroyer&lt;false&gt;::execute&lt;const T&gt;(volatile const T *)' being compiled with [ </p> <blockquote> <p> T=const Foo3 </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/detail/destroy.hpp(101) : see reference to function template instantiation 'void boost::python::detail::destroy_referent_impl&lt;T&gt;(void *,T &amp;(<span class="underline">cdecl *)(void))' being compiled with [ </span></p> <blockquote> <p> T=const Foo3 </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/converter/rvalue_from_python_data.hpp(135) : see reference to function template instantiation 'void boost::python::detail::destroy_referent&lt;const Foo3&amp;&gt;(void *,T (<span class="underline">cdecl *)(void))' being compiled with [ </span></p> <blockquote> <p> T=const Foo3 &amp; </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/converter/rvalue_from_python_data.hpp(133) : while compiling class template member function 'boost::python::converter::rvalue_from_python_data&lt;T&gt;::~rvalue_from_python_data(void)' with [ </p> <blockquote> <p> T=const Foo3 &amp; </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/converter/arg_from_python.hpp(124) : see reference to class template instantiation 'boost::python::converter::rvalue_from_python_data&lt;T&gt;' being compiled with [ </p> <blockquote> <p> T=const Foo3 &amp; </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/arg_from_python.hpp(27) : see reference to class template instantiation 'boost::python::converter::arg_rvalue_from_python&lt;T&gt;' being compiled with [ </p> <blockquote> <p> T=const Foo3 &amp; </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/preprocessor/iteration/detail/local.hpp(37) : see reference to class template instantiation 'boost::python::arg_from_python&lt;T&gt;' being compiled with [ </p> <blockquote> <p> T=const Foo3 &amp; </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/detail/caller.hpp(200) : while compiling class template member function '<a class="missing wiki">PyObject</a> *boost::python::detail::caller_arity&lt;2&gt;::impl&lt;F,Policies,Sig&gt;::operator ()(<a class="missing wiki">PyObject</a> *,<a class="missing wiki">PyObject</a> *)' with [ </p> <blockquote> <p> F=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), Policies=boost::python::default_call_policies, Sig=boost::mpl::vector3&lt;void,Foo4 &amp;,const Foo3 &amp;&gt; </span></p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/detail/caller.hpp(169) : see reference to class template instantiation 'boost::python::detail::caller_arity&lt;2&gt;::impl&lt;F,Policies,Sig&gt;' being compiled with [ </p> <blockquote> <p> F=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), Policies=boost::python::default_call_policies, Sig=boost::mpl::vector3&lt;void,Foo4 &amp;,const Foo3 &amp;&gt; </span></p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/make_function.hpp(61) : see reference to class template instantiation 'boost::python::detail::caller&lt;F,<a class="missing wiki">CallPolicies</a>,Sig&gt;' being compiled with [ </p> <blockquote> <p> F=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), <a class="missing wiki">CallPolicies</a>=boost::python::default_call_policies, Sig=boost::mpl::vector3&lt;void,Foo4 &amp;,const Foo3 &amp;&gt; </span></p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/make_function.hpp(146) : see reference to function template instantiation 'boost::python::api::object boost::python::detail::make_function_aux&lt;F,<a class="missing wiki">CallPolicies</a>,Signature,boost::mpl::int_&lt;N&gt;&gt;(F,const <a class="missing wiki">CallPolicies</a> &amp;,const Sig &amp;,const boost::python::detail::keyword_range &amp;,<a class="missing wiki">NumKeywords</a>)' being compiled with [ </p> <blockquote> <p> F=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), <a class="missing wiki">CallPolicies</a>=boost::python::default_call_policies, Signature=boost::mpl::vector3&lt;void,Foo4 &amp;,const Foo3 &amp;&gt;, N=1, Sig=boost::mpl::vector3&lt;void,Foo4 &amp;,const Foo3 &amp;&gt;, <a class="missing wiki">NumKeywords</a>=boost::mpl::int_&lt;1&gt; </span></p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/class.hpp(544) : see reference to function template instantiation 'boost::python::api::object boost::python::make_function&lt;Fn,boost::python::default_call_policies,T1,boost::mpl::vector3&lt;T0,Foo4 &amp;,T2&gt;&gt;(F,const <a class="missing wiki">CallPolicies</a> &amp;,const Keywords &amp;,const Signature &amp;)' being compiled with [ </p> <blockquote> <p> Fn=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), T1=boost::python::detail::keywords&lt;1&gt;, T0=void, T2=const Foo3 &amp;, F=void (</span>thiscall Foo4::* )(const Foo3 &amp;), <a class="missing wiki">CallPolicies</a>=boost::python::default_call_policies, Keywords=boost::python::detail::keywords&lt;1&gt;, Signature=boost::mpl::vector3&lt;void,Foo4 &amp;,const Foo3 &amp;&gt; </p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/class.hpp(614) : see reference to function template instantiation 'void boost::python::class_&lt;W&gt;::def_impl&lt;Foo4,Fn,boost::python::detail::def_helper&lt;T1&gt;&gt;(T *,const char *,Fn,const Helper &amp;,...)' being compiled with [ </p> <blockquote> <p> W=Foo4, Fn=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), T1=boost::python::detail::keywords&lt;1&gt;, T=Foo4, Helper=boost::python::detail::def_helper&lt;boost::python::detail::keywords&lt;1&gt;&gt; </span></p> </blockquote> <p> ] C:/Program Files/boost/boost_1_42\boost/python/class.hpp(244) : see reference to function template instantiation 'void boost::python::class_&lt;W&gt;::def_maybe_overloads&lt;A1,A2&gt;(const char *,Fn,const boost::python::detail::keywords&lt;1&gt; &amp;,...)' being compiled with [ </p> <blockquote> <p> W=Foo4, A1=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), A2=boost::python::detail::keywords&lt;1&gt;, Fn=void (</span>thiscall Foo4::* )(const Foo3 &amp;) </p> </blockquote> <p> ] wrap_foo.cpp(21) : see reference to function template instantiation 'boost::python::class_&lt;W&gt; &amp;boost::python::class_&lt;W&gt;::def&lt;void(<span class="underline">thiscall Foo4::* )(const Foo3 &amp;),boost::python::detail::keywords&lt;1&gt;&gt;(const char *,A1,const A2 &amp;)' being compiled with [ </span></p> <blockquote> <p> W=Foo4, A1=void (<span class="underline">thiscall Foo4::* )(const Foo3 &amp;), A2=boost::python::detail::keywords&lt;1&gt; </span></p> </blockquote> <p> ] </p> </blockquote> <p> error: command '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe"' failed with exit status 2 ######################################################### </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4003 Trac 1.4.3 Christopher Bruns <cmbruns@…> Sat, 13 Mar 2010 18:18:02 GMT attachment set https://svn.boost.org/trac10/ticket/4003 https://svn.boost.org/trac10/ticket/4003 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">foo.h</span> </li> </ul> <p> minimized example header file to be wrapped </p> Ticket Christopher Bruns <cmbruns@…> Sat, 13 Mar 2010 18:19:48 GMT attachment set https://svn.boost.org/trac10/ticket/4003 https://svn.boost.org/trac10/ticket/4003 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">wrap_foo.cpp</span> </li> </ul> <p> boost.python wrapping code for minimal example </p> Ticket Christopher Bruns <cmbruns@…> Sat, 13 Mar 2010 18:19:50 GMT attachment set https://svn.boost.org/trac10/ticket/4003 https://svn.boost.org/trac10/ticket/4003 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">wrap_foo.2.cpp</span> </li> </ul> <p> boost.python wrapping code for minimal example </p> Ticket Christopher Bruns <cmbruns@…> Sat, 13 Mar 2010 18:20:42 GMT attachment set https://svn.boost.org/trac10/ticket/4003 https://svn.boost.org/trac10/ticket/4003 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">inadequate_patch.patch</span> </li> </ul> <p> (imperfect) patch for destroy.hpp </p> Ticket Christopher Bruns <cmbruns@…> Sat, 13 Mar 2010 18:22:29 GMT <link>https://svn.boost.org/trac10/ticket/4003#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4003#comment:1</guid> <description> <p> Sorry about the two copies of wrap_foo.cpp. In my impatience I hit the "submit" button twice. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Mon, 15 Mar 2010 21:57:39 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4003#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4003#comment:2</guid> <description> <p> It seems to work if I change the code to </p> <pre class="wiki">p-&gt;~T() </pre><p> However, this is slightly different, since it will invoke a virtual destructor, where the original will not. The only other alternative I can think of it to mangle the name so that there is no chance of anyone using the same name. (i.e. template&lt;class T_boost_python_unique_id_82623817364646282&gt;) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Dave Abrahams</dc:creator> <pubDate>Tue, 16 Mar 2010 18:25:40 GMT</pubDate> <title>owner changed https://svn.boost.org/trac10/ticket/4003#comment:3 https://svn.boost.org/trac10/ticket/4003#comment:3 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Dave Abrahams</span> to <span class="trac-author">Steven Watanabe</span> </li> </ul> <p> Isn't using a virtual d'tor OK here? </p> <p> What about a simple typedef either inside the function body or in the body of the class? Does VC still look up the wrong name? </p> Ticket Steven Watanabe Tue, 16 Mar 2010 19:35:15 GMT owner changed https://svn.boost.org/trac10/ticket/4003#comment:4 https://svn.boost.org/trac10/ticket/4003#comment:4 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Steven Watanabe</span> to <span class="trac-author">Dave Abrahams</span> </li> </ul> <p> I would assume that a virtual destructor is okay, but I didn't write the code in question. A typedef doesn't seem to help. The first name after the -&gt; always seems to be looked up in the context of T first. I even tried this: </p> <pre class="wiki">template&lt;class T&gt; struct Destroyer { typedef T Type; static void destroy(T* t) { t-&gt;Destroyer&lt;Type&gt;::Type::~Type(); } }; struct S { void Type(); void Destroyer(); }; int main() { S t; Destroyer&lt;S&gt;::destroy(&amp;t); } </pre><p> and it still fails. </p> Ticket anonymous Wed, 17 Mar 2010 20:40:46 GMT <link>https://svn.boost.org/trac10/ticket/4003#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4003#comment:5</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/4003#comment:4" title="Comment 4">steven_watanabe</a>: </p> <blockquote class="citation"> <p> I would assume that a virtual destructor is okay, but I didn't write the code in question. </p> </blockquote> <p> Feel free to check in your fix, preferably after having run the tests once :-) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Fri, 26 Mar 2010 19:04:42 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/4003#comment:6 https://svn.boost.org/trac10/ticket/4003#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/60868" title="Handle the destructor call in a way that keeps msvc happy. Fixes #4003">[60868]</a>) Handle the destructor call in a way that keeps msvc happy. Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4003" title="#4003: Bugs: Error in destroy.hpp when methods &#34;T()&#34; and &#34;operator~()&#34; are defined. (closed: fixed)">#4003</a> </p> Ticket