paulgessinger
paulgessinger

Reputation: 163

Type trait on std::reference_wrapper<std::any>

std::reference_wrapper should be copy-constructible, regardless of the contained type (it's just a pointer inside). However, when asserting that using

static_assert(std::is_copy_constructible<std::reference_wrapper<std::any> >::value, "!");

Clang terminates with a compile error from inside the STL, while GCC reports no problems. This is not the case with other types (I tested std::reference_wrapper<int> and std::any directly).

I have an example showing compilation in GCC and Clang at https://godbolt.org/z/7YwkWb.

As far as I understand it, even if the type given to std::is_copy_constructible is not copy-constructible, it should just give a compile-time false, rather than failing compilation. What is the problem here? Is that a compiler bug or am I missing something?

The compile error from Clang is:

In file included from <source>:1:
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:132:31: error: no member named 'value' in 'std::is_copy_constructible<std::reference_wrapper<std::any> >'
    : public conditional<_B1::value, _B2, _B1>::type
                         ~~~~~^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/any:170:17: note: in instantiation of template class 'std::__and_<std::is_copy_constructible<std::reference_wrapper<std::any> >, std::is_constructible<std::reference_wrapper<std::any>, const std::reference_wrapper<std::any> &> >' requested here
      enable_if<__and_<is_copy_constructible<_Tp>,
                ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/any:175:5: note: in instantiation of template type alias '__any_constructible' requested here
    using __any_constructible_t =
    ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/any:181:56: note: in instantiation of template type alias '__any_constructible_t' requested here
              __any_constructible_t<_Tp, _ValueType&&> = true,
                                                       ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/any:183:7: note: while substituting prior template arguments into non-type template parameter [with _ValueType = const std::reference_wrapper<std::any> &, _Tp = std::reference_wrapper<std::any>, _Mgr = std::any::_Manager_internal<std::reference_wrapper<std::any> >]
      any(_ValueType&& __value)
      ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:921:56: note: while substituting deduced template arguments into function template 'any' [with _ValueType = const std::reference_wrapper<std::any> &, _Tp = (no value), _Mgr = (no value), $3 = (no value), $4 = (no value)]
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                                                       ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:933:14: note: in instantiation of template class 'std::is_constructible<std::reference_wrapper<std::any>, const std::reference_wrapper<std::any> &>' requested here
    : public is_constructible<_Tp, const _Tp&>
             ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:939:14: note: in instantiation of template class 'std::__is_copy_constructible_impl<std::reference_wrapper<std::any>, true>' requested here
    : public __is_copy_constructible_impl<_Tp>
             ^
<source>:12:20: note: in instantiation of template class 'std::is_copy_constructible<std::reference_wrapper<std::any> >' requested here
static_assert(std::is_copy_constructible<std::reference_wrapper<std::any> >::value, "!");
                   ^
In file included from <source>:1:
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:137:31: error: no member named 'value' in 'std::is_copy_constructible<std::reference_wrapper<std::any> >'
    : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
                         ~~~~~^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/any:192:27: note: in instantiation of template class 'std::__and_<std::is_copy_constructible<std::reference_wrapper<std::any> >, std::__not_<std::is_constructible<std::reference_wrapper<std::any>, const std::reference_wrapper<std::any> &> >, std::__not_<std::__is_in_place_type<std::reference_wrapper<std::any> > > >' requested here
              enable_if_t<__and_<is_copy_constructible<_Tp>,
                          ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/any:196:7: note: while substituting prior template arguments into non-type template parameter [with _ValueType = const std::reference_wrapper<std::any> &, _Tp = std::reference_wrapper<std::any>, _Mgr = std::any::_Manager_internal<std::reference_wrapper<std::any> >]
      any(_ValueType&& __value)
      ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:921:56: note: while substituting deduced template arguments into function template 'any' [with _ValueType = const std::reference_wrapper<std::any> &, _Tp = (no value), _Mgr = (no value), $3 = (no value)]
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                                                       ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:933:14: note: in instantiation of template class 'std::is_constructible<std::reference_wrapper<std::any>, const std::reference_wrapper<std::any> &>' requested here
    : public is_constructible<_Tp, const _Tp&>
             ^
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/type_traits:939:14: note: in instantiation of template class 'std::__is_copy_constructible_impl<std::reference_wrapper<std::any>, true>' requested here
    : public __is_copy_constructible_impl<_Tp>
             ^
<source>:12:20: note: in instantiation of template class 'std::is_copy_constructible<std::reference_wrapper<std::any> >' requested here
static_assert(std::is_copy_constructible<std::reference_wrapper<std::any> >::value, "!");
                   ^
2 errors generated.
Compiler returned: 1

Upvotes: 3

Views: 276

Answers (1)

The error you see clearly states at the top that std::is_copy_constructible doesn't have a value member for the specialization you check. Now, the types you pass don't violate the contract of std::is_copy_constructible, so there is no risk of undefined behavior.

Which means only one thing, it's not a compiler issue, but a standard library implementation issue. Clang uses the default installed standard library implementation, which on the system godbolt is running is libstdc++ (the GNU implementation). This evidently causes the issue due to some possible soft incompatibility.

If you specify the -stdlib=libc++ option (libc++ is the LLVM implementation of the standard library) when building with Clang, then it accepts the code fine.

Upvotes: 3

Related Questions