
On 27 Jun 2017, at 20:09, dariomt--- via Boost-users <boost-users@lists.boost.org> wrote:
#include <boost/variant.hpp> class A {}; class B : private A {}; typedef boost::variant<A, B> variant_t; int main() { B b; variant_t v (b); }
In `boost/type_traits/is_convertible.hpp`: ``` 123 struct any_conversion 124 { 125 template <typename T> any_conversion(const volatile T&); 126 template <typename T> any_conversion(const T&); 127 template <typename T> any_conversion(volatile T&); 128 template <typename T> any_conversion(T&); 129 }; 130 131 template <typename T> struct checker 132 { 133 static boost::type_traits::no_type _m_check(any_conversion ...); 134 static boost::type_traits::yes_type _m_check(T, int); 135 }; ``` And according to [https://stackoverflow.com/questions/30004771/why-is-a-malformed-function-use...], the standard conversion sequence takes precedence of the user-defined conversion (`any_conversion`), hence `checker<A>::_m_check(B(), 0)` results in a hard error. So I suspect this is a bug in 'type_traits' library, but I'm not sure. Hopefully somebody else can confirm. (I'm sorry but I don't know to whom should I CC this post.) An easy workaround would be specializing `boost::is_convertible` for your classes: ``` namespace boost { template <> struct is_convertible<B&, A> : boost::false_type {}; template <> struct is_convertible<const B&, A> : boost::false_type {}; } ``` I don't know why clang accepts your code though. Perhaps `boost::is_convertible` is conditionally compiled to some different implementations in Clang. ------ A reduced repo of the hard error in `boost::is_convertible` is: ``` struct any_conversion { template <typename T> any_conversion(const volatile T&); template <typename T> any_conversion(const T&); template <typename T> any_conversion(volatile T&); template <typename T> any_conversion(T&); }; typedef char (&yes_type)[2]; typedef char (&no_type)[1]; class A {}; class B : private A {}; static no_type _m_check(any_conversion ...); static yes_type _m_check(A, int); int main() { B b; _m_check(b, 0); } ``` Both GCC and Clang reject it.