|
Boost Users : |
Subject: Re: [Boost-users] Regression in Boost.Variant with gcc6.3 in C++03 mode
From: d25fe0be_at_[hidden]
Date: 2017-06-27 15:46:24
> On 27 Jun 2017, at 20:09, dariomt--- via Boost-users <boost-users_at_[hidden]> 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-used-instead-of-an-implicit-conversion], 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.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net