Boost C++ Libraries: Ticket #9913: boost::has_complement of enum class does not compile https://svn.boost.org/trac10/ticket/9913 <p> (Also filed this as a gcc bug at <a class="ext-link" href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60852"><span class="icon">​</span>http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60852</a>) </p> <p> This works under gcc 4.7.2 and clang 3.4, but fails to compile under gcc 4.9 RC1. enum class seems to be the only issue; plain enums work fine. </p> <p> #include &lt;boost/type_traits.hpp&gt; #include &lt;iostream&gt; </p> <p> enum class E {}; </p> <p> int main() { std::cout &lt;&lt; boost::has_complement&lt;E&gt;() &lt;&lt; std::endl; } </p> <p> Using Boost 1.55 and g++ -std=c++11, we get: </p> <p> In file included from /opt/local/include/boost/config.hpp:57:0, </p> <blockquote> <p> from /opt/local/include/boost/type_traits/add_const.hpp:13, from /opt/local/include/boost/type_traits.hpp:13, from a.cpp:1: </p> </blockquote> <p> /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp: In instantiation of 'const bool boost::detail::has_complement_impl::operator_exists&lt;E&gt;::value': /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:173:4: required from 'const bool boost::detail::has_complement_impl::trait_impl1&lt;E, boost::detail::has_complement_impl::dont_care, false&gt;::value' /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:195:4: required from 'const bool boost::detail::has_complement_impl::trait_impl&lt;E, boost::detail::has_complement_impl::dont_care&gt;::value' /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:202:1: required from 'struct boost::has_complement&lt;E&gt;' a.cpp:7:41: required from here /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:152:56: error: no match for 'operator~' (operand type is 'E') </p> <blockquote> <p> BOOST_STATIC_CONSTANT(bool, value = (sizeof(check(((BOOST_TT_TRAIT_OP make&lt;Rhs&gt;()),make&lt;has_operator&gt;())))==sizeof(::boost::type_traits::yes_type))); </p> <blockquote> <p> <sup> </sup></p> </blockquote> </blockquote> <p> /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp: In instantiation of 'const bool boost::detail::has_complement_impl::operator_returns_void&lt;E&gt;::value': /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:173:4: required from 'const bool boost::detail::has_complement_impl::trait_impl1&lt;E, boost::detail::has_complement_impl::dont_care, false&gt;::value' /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:195:4: required from 'const bool boost::detail::has_complement_impl::trait_impl&lt;E, boost::detail::has_complement_impl::dont_care&gt;::value' /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:202:1: required from 'struct boost::has_complement&lt;E&gt;' a.cpp:7:41: required from here /opt/local/include/boost/type_traits/detail/has_prefix_operator.hpp:89:102: error: no match for 'operator~' (operand type is 'E') </p> <blockquote> <p> BOOST_STATIC_CONSTANT(bool, value = (sizeof(::boost::type_traits::yes_type)==sizeof(returns_void((BOOST_TT_TRAIT_OP make&lt;Rhs&gt;(),returns_void_t()))))); </p> <blockquote> <p> <sup> </sup></p> </blockquote> </blockquote> <p> a.cpp: In function 'int main()': a.cpp:7:41: error: cannot bind 'std::ostream {aka std::basic_ostream&lt;char&gt;}' lvalue to 'std::basic_ostream&lt;char&gt;&amp;&amp;' </p> <blockquote> <p> { std::cout &lt;&lt; boost::has_complement&lt;E&gt;() &lt;&lt; std::endl; } </p> <blockquote> <p> <sup> </sup></p> </blockquote> </blockquote> <p> In file included from /opt/local/include/gcc49/c++/istream:39:0, </p> <blockquote> <p> from /opt/local/include/gcc49/c++/sstream:38, from /opt/local/include/gcc49/c++/complex:45, from /opt/local/include/boost/type_traits/is_complex.hpp:12, from /opt/local/include/boost/type_traits.hpp:49, from a.cpp:1: </p> </blockquote> <p> /opt/local/include/gcc49/c++/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;&amp;&amp;, const _Tp&amp;) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; _Tp = boost::has_complement&lt;E&gt;]' </p> <blockquote> <p> operator&lt;&lt;(basic_ostream&lt;_CharT, _Traits&gt;&amp;&amp; <span class="underline">os, const _Tp&amp; </span>x) <sup> </sup></p> </blockquote> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9913 Trac 1.4.3 Nevin Liber <nevin@…> Tue, 15 Apr 2014 19:36:18 GMT attachment set https://svn.boost.org/trac10/ticket/9913 https://svn.boost.org/trac10/ticket/9913 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">a.cpp</span> </li> </ul> <p> Reproducible test case </p> Ticket Nevin Liber <nevin@…> Wed, 16 Apr 2014 14:27:55 GMT <link>https://svn.boost.org/trac10/ticket/9913#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9913#comment:1</guid> <description> <p> Discussion on Stack Overflow seems to indicate the bug is in Boost: &lt;<a class="ext-link" href="http://stackoverflow.com/questions/23108590/is-this-valid-c11"><span class="icon">​</span>http://stackoverflow.com/questions/23108590/is-this-valid-c11</a>&gt;. </p> </description> <category>Ticket</category> </item> <item> <author>Nevin Liber <nevin@…></author> <pubDate>Wed, 16 Apr 2014 21:29:44 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9913#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9913#comment:2</guid> <description> <p> Bug filed against clang current behavior &lt;<a class="ext-link" href="http://llvm.org/bugs/show_bug.cgi?id=19452"><span class="icon">​</span>http://llvm.org/bugs/show_bug.cgi?id=19452</a>&gt;. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Wed, 23 Apr 2014 12:29:56 GMT</pubDate> <title>owner changed https://svn.boost.org/trac10/ticket/9913#comment:3 https://svn.boost.org/trac10/ticket/9913#comment:3 <ul> <li><strong>owner</strong> changed from <span class="trac-author">John Maddock</span> to <span class="trac-author">bronf</span> </li> </ul> <p> Confirmed that this is a problem with our code - it seems that class enum's are unique in not accepting these operator overloads. Given that, I'm actually not sure if it's even possible to implement has*operator for class enum types :-( </p> <p> Reassigning to the author of those files in the hopes of a fix.... </p> Ticket Nevin Liber <nevin@…> Wed, 23 Apr 2014 15:51:28 GMT <link>https://svn.boost.org/trac10/ticket/9913#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9913#comment:4</guid> <description> <p> Here is my C++11 only version of has_complement: </p> <pre class="wiki"> namespace detail { namespace has_complement_impl { struct dont_care {}; template&lt;typename Rhs, typename Ret&gt; class has_complement_trait { template&lt;typename Hs, typename Et = decltype(~std::declval&lt;Hs&gt;()), typename = typename std::enable_if&lt;std::is_same&lt;dont_care, Ret&gt;::value || std::is_convertible&lt;Et, Ret&gt;::value&gt;::type&gt; static true_type has_complement_operator(int); template&lt;typename&gt; static false_type has_complement_operator(...); public: using type = decltype(has_complement_operator&lt;Rhs&gt;(0)); }; }; // has_complement_impl namespace } // detail namespace template&lt;typename Rhs, typename Ret = detail::has_complement_impl::dont_care&gt; struct has_complement : detail::has_complement_impl::has_complement_trait&lt;Rhs, Ret&gt;::type {}; </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Wed, 23 Apr 2014 17:06:51 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9913#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9913#comment:5</guid> <description> <p> Thanks that's really neat! </p> <p> Hopefully Frederic Bron will take this up as he's much more familiar with the internals of these traits than I am. </p> <p> Note that the issue effects not just the unary operators, but all the binary operators such as has_plus etc suffer the same issue. </p> <p> We also need to figure out what config macros will determine when the above approach can be used - BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS and BOOST_NO_CXX11_DECLTYPE certainly, possibly BOOST_NO_SFINAE_EXPR as well. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Thu, 02 Aug 2018 11:31:12 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9913#comment:6 https://svn.boost.org/trac10/ticket/9913#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">obsolete</span> </li> </ul> <p> Moved to <a class="ext-link" href="https://github.com/boostorg/type_traits/issues/80"><span class="icon">​</span>https://github.com/boostorg/type_traits/issues/80</a> </p> Ticket