|
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