Boost logo

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 17:27:19


> On 28 Jun 2017, at 00:53, dariomt_at_[hidden] wrote:
>
>
> 2017-06-27 17:46 GMT+02:00 d25fe0be_at_[hidden] <d25fe0be_at_[hidden]>:
> 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.)
>
> I don't know why clang accepts your code though. Perhaps `boost::is_convertible` is conditionally compiled to some different implementations in Clang.
>
> Thanks for the analysis.
> My guess is that clang uses a different implementation of is_convertible.
> Also, I guess this works in C++14 because std::is_convertible is used instead?

Yes, after a deeper dig, `boost/type_traits/intrinsics.hpp` shows that `type_traits` uses Clang's intrinsics to do the job:

```
   157 #if defined(BOOST_CLANG) && defined(__has_feature) && !defined(__CUDACC__)
   [...]
   213 # if __has_feature(is_convertible_to)
   214 # define BOOST_IS_CONVERTIBLE(T,U) __is_convertible_to(T,U)
   215 # endif
```

After commenting out macro `BOOST_IS_CONVERTIBLE`, clang errors out the original code as well.

And I believe this finding gives us an easier workaround: Just defining our own `BOOST_IS_CONVERTIBLE` before including `boost/variant.hpp`, and the compilation error should disappear.

```
#include <type_traits>
#define BOOST_IS_CONVERTIBLE(T,U) std::is_convertible<T, U>::value

#include <boost/variant.hpp>
[...]
```

As for the implementation of `boost::is_convertible` in C++14, although I agree with you that `type_traits` could (or should have?) use std::is_convertible when available, `boost/type_traits/is_convertible.hpp` shows that `type_traits` implemented their own C++11 version:

```
    53 //
    54
    55 namespace detail {
    56
    57 #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(BOOST_GCC) && (BOOST_GCC < 40700))
    58
    59 // This is a C++11 conforming version, place this first and use it wherever possible:
    60
    61 # define BOOST_TT_CXX11_IS_CONVERTIBLE
    62
    63 template <class A, class B, class C>
    64 struct or_helper
    65 {
    66 static const bool value = (A::value || B::value || C::value);
    67 };
    68
    69 template<typename From, typename To, bool b = or_helper<boost::is_void<From>, boost::is_function<To>, boost::is_array<To> >::value>
    70 struct is_convertible_basic_impl
    71 {
    72 // Nothing converts to function or array, but void converts to void:
    73 static const bool value = is_void<To>::value;
    74 };
    75
    76 template<typename From, typename To>
    77 class is_convertible_basic_impl<From, To, false>
    78 {
    79 typedef char one;
```


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