Compiler Explorer link: https://godbolt.org/z/RCoRVj The following code: ``` #include <any> #include <tuple> #include <type_traits> bool is_copy_constructible_tuple_any() { return std::is_copy_constructible<std::tuple<std::any>>::value; } ``` when compiled with GCC 9.1 and `-Wall -Wextra -std=c++17` results in a rather elaborate error message: ``` In file included from /usr/include/c++/9/bits/move.h:55, from /usr/include/c++/9/bits/nested_exception.h:40, from /usr/include/c++/9/exception:144, from /usr/include/c++/9/new:40, from /usr/include/c++/9/any:37, from test.cc:1: /usr/include/c++/9/type_traits: In instantiation of ‘struct std::__and_<std::is_copy_constructible<std::tuple<std::any> >, std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&> >’: /usr/include/c++/9/any:181:58: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous>, typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const std::tuple<std::any>&; _Tp = std::tuple<std::any>; _Mgr = std::any::_Manager_external<std::tuple<std::any> >; typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _ValueType&&> >::value, bool>::type <anonymous> = <missing>; typename std::enable_if<(! std::__is_in_place_type<_Tp>::value), bool>::type <anonymous> = <missing>]’ /usr/include/c++/9/type_traits:931:12: required from ‘struct std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&>’ /usr/include/c++/9/type_traits:943:12: required from ‘struct std::__is_copy_constructible_impl<std::tuple<std::any>, true>’ /usr/include/c++/9/type_traits:949:12: required from ‘struct std::is_copy_constructible<std::tuple<std::any> >’ test.cc:6:60: required from here /usr/include/c++/9/type_traits:131:12: error: incomplete type ‘std::is_copy_constructible<std::tuple<std::any> >’ used in nested name specifier 131 | struct __and_<_B1, _B2> | ^~~~~~~~~~~~~~~~ /usr/include/c++/9/type_traits: In instantiation of ‘struct std::__and_<std::is_copy_constructible<std::tuple<std::any> >, std::__not_<std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&> >, std::__not_<std::__is_in_place_type<std::tuple<std::any> > > >’: /usr/include/c++/9/type_traits:150:27: required from ‘constexpr const bool std::__and_v<std::is_copy_constructible<std::tuple<std::any> >, std::__not_<std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&> >, std::__not_<std::__is_in_place_type<std::tuple<std::any> > > >’ /usr/include/c++/9/any:192:27: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const std::tuple<std::any>&; _Tp = std::tuple<std::any>; _Mgr = std::any::_Manager_external<std::tuple<std::any> >; typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> = <missing>]’ /usr/include/c++/9/type_traits:931:12: required from ‘struct std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&>’ /usr/include/c++/9/type_traits:943:12: required from ‘struct std::__is_copy_constructible_impl<std::tuple<std::any>, true>’ /usr/include/c++/9/type_traits:949:12: required from ‘struct std::is_copy_constructible<std::tuple<std::any> >’ test.cc:6:60: required from here /usr/include/c++/9/type_traits:136:12: error: incomplete type ‘std::is_copy_constructible<std::tuple<std::any> >’ used in nested name specifier 136 | struct __and_<_B1, _B2, _B3, _Bn...> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/c++/9/type_traits: In instantiation of ‘constexpr const bool std::__and_v<std::is_copy_constructible<std::tuple<std::any> >, std::__not_<std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&> >, std::__not_<std::__is_in_place_type<std::tuple<std::any> > > >’: /usr/include/c++/9/any:192:27: required by substitution of ‘template<class _ValueType, class _Tp, class _Mgr, typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> > std::any::any(_ValueType&&) [with _ValueType = const std::tuple<std::any>&; _Tp = std::tuple<std::any>; _Mgr = std::any::_Manager_external<std::tuple<std::any> >; typename std::enable_if<__and_v<std::is_copy_constructible<_Tp>, std::__not_<std::is_constructible<_Tp, _ValueType&&> >, std::__not_<std::__is_in_place_type<_Tp> > >, bool>::type <anonymous> = <missing>]’ /usr/include/c++/9/type_traits:931:12: required from ‘struct std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&>’ /usr/include/c++/9/type_traits:943:12: required from ‘struct std::__is_copy_constructible_impl<std::tuple<std::any>, true>’ /usr/include/c++/9/type_traits:949:12: required from ‘struct std::is_copy_constructible<std::tuple<std::any> >’ test.cc:6:60: required from here /usr/include/c++/9/type_traits:150:27: error: ‘value’ is not a member of ‘std::__and_<std::is_copy_constructible<std::tuple<std::any> >, std::__not_<std::is_constructible<std::tuple<std::any>, const std::tuple<std::any>&> >, std::__not_<std::__is_in_place_type<std::tuple<std::any> > > >’ 150 | inline constexpr bool __and_v = __and_<_Bn...>::value; | ```
This bug was present when gcc 8 branched. It was fixed in the gcc 8 branch, but I guess it was never fixed on trunk. On the gcc 8 branch it was fixed by r261463 (d26c6b8b0c6abba9a67b87a1d48f0c3165d021cc).
The bug is still present on trunk.
I see now that the corresponding commit on trunk was 31011b9a94fed33170c009292e82558336d1c4d7 (r261146). At that revision, the test in this bug passes. There was a more recent regression on trunk on revision a9b768f8f4fd471e315623b23c4f9e83463bf92e (r270433).
Thanks for the bisection. Changing component to c++ for now, although it's possible a fix is needed in the library.
I think this is a libstdc++ bug, because Clang has always rejected the example with any version of the libstdc++ headers. And I know what's going on, and might have a fix.
This issue prevents using std::any with gmock, which I need it for the unit tests to pass the build. There are related SO questions: * https://stackoverflow.com/questions/57332965/incomplete-type-for-stdany-when-gmocking-interface * https://stackoverflow.com/questions/57387245/using-stdany-with-gmock-result-in-different-behavior-on-gcc-79 @Jonathan Wakely Is there a quick fix for this? I would like to test it.
Additional information. std::experimental::fundamentals_v1::any has no problem, so the below code compiles fine. ``` #include <experimental/any> #include <tuple> #include <type_traits> bool is_copy_constructible_tuple_any() { return std::is_copy_constructible<std::tuple<std::experimental::any>>::value; } ```
(In reply to Lei YU from comment #6) > @Jonathan Wakely Is there a quick fix for this? I would like to test it. If I had a fix I would have committed it.
(In reply to Lei YU from comment #7) > Additional information. > > std::experimental::fundamentals_v1::any has no problem, so the below code > compiles fine. The difference is that std::experimental::any doesn't constrain the any(T&&) constructor on is_copy_constructible<T>, instead it just makes it a hard error (using a static assert in the constructor body). std::any has to SFINAE the any(T&&) constructor away if T is not copy constructible, which leads to a cycle when that constructor is being considered during instantiation of is_copy_constructible<T>.
GCC 9.3.0 has been released, adjusting target milestone.
Here's an interesting reduction: #include <type_traits> struct any { any(); any(any const&); template <class ValueType , class Tp = std::decay_t<ValueType> , class = std::enable_if_t< !std::is_same<Tp, any>::value && std::is_copy_constructible<Tp>::value #ifdef LIBSTDCXX && std::is_constructible<Tp, ValueType>::value #endif > > any(ValueType&& value); }; struct X { X(X const&); X(any); }; static_assert(std::is_copy_constructible_v<X>); This compiles fine, fails if you add -DLIBSTDCXX. I laid it out this way because libstdc++ has that check but libc++ doesn't. Although, this is especially weird because in this program, there is only one instantiation of any's constructor template and it's with ValueType=X const&, which means that we're checking is_copy_constructible<X> && is_constructible<X, X const&>... which should be identical and yet are somehow not.
*** Bug 91630 has been marked as a duplicate of this bug. ***
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:d1462b0782555354b4480e1f46498586d5882972 commit r10-7935-gd1462b0782555354b4480e1f46498586d5882972 Author: Jonathan Wakely <jwakely@redhat.com> Date: Fri Apr 24 00:54:20 2020 +0100 libstdc++: Fix constructor constraints for std::any (PR 90415) This removes a non-standard extension to std::any which causes errors for valid code, due to recursive instantiation of a trait that isn't supposed to be in the constraints. It also removes some incorrect constraints on the in_place_type<T> constructors and emplace members, which were preventing creating a std::any object with another std::any as the contained value. 2020-04-24 Kamlesh Kumar <kamleshbhalui@gmail.com> Jonathan Wakely <jwakely@redhat.com> PR libstdc++/90415 PR libstdc++/92156 * include/std/any (any): Rename template parameters for consistency with the standard. (any::_Decay): Rename to _Decay_if_not_any. (any::any(T&&):: Remove is_constructible from constraints. Remove non-standard overload. (any::any(in_place_type_t<T>, Args&&...)) (any::any(in_place_type_t<T>, initializer_list<U>, Args&&...)) (any::emplace(Args&&...)) (any::emplace(initializer_list<U>, Args&&...)): Use decay_t instead of _Decay. * testsuite/20_util/any/cons/90415.cc: New test. * testsuite/20_util/any/cons/92156.cc: New Test. * testsuite/20_util/any/misc/any_cast_neg.cc: Make dg-error directives more robust. * testsuite/20_util/any/modifiers/92156.cc: New test.
Fixed on master so far, backport to follow soon.
I have nearly the same issue (g++ compiles fine, but clang++ not). Not with std::any as tuple argument, but some references to other tuple types. I "solved" it, by using my own std::is_copy_constructible. using my_is_copy_constructible = std::is_constructible_v<T, std::add_lvalue_reference_t<const T>>;
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
The releases/gcc-9 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:14597b680a24b6f7375e4470dea935da9c369feb commit r9-9638-g14597b680a24b6f7375e4470dea935da9c369feb Author: Jonathan Wakely <jwakely@redhat.com> Date: Fri Apr 24 00:54:20 2020 +0100 libstdc++: Fix constructor constraints for std::any (PR 90415) This removes a non-standard extension to std::any which causes errors for valid code, due to recursive instantiation of a trait that isn't supposed to be in the constraints. It also removes some incorrect constraints on the in_place_type<T> constructors and emplace members, which were preventing creating a std::any object with another std::any as the contained value. 2020-04-24 Kamlesh Kumar <kamleshbhalui@gmail.com> Jonathan Wakely <jwakely@redhat.com> PR libstdc++/90415 PR libstdc++/92156 * include/std/any (any): Rename template parameters for consistency with the standard. (any::_Decay): Rename to _Decay_if_not_any. (any::any(T&&)): Remove is_constructible from constraints. Remove non-standard overload. (any::any(in_place_type_t<T>, Args&&...)) (any::any(in_place_type_t<T>, initializer_list<U>, Args&&...)) (any::emplace(Args&&...)) (any::emplace(initializer_list<U>, Args&&...)): Use decay_t instead of _Decay. * testsuite/20_util/any/cons/90415.cc: New test. * testsuite/20_util/any/cons/92156.cc: New Test. * testsuite/20_util/any/misc/any_cast_neg.cc: Make dg-error directives more robust. * testsuite/20_util/any/modifiers/92156.cc: New test. (cherry picked from commit d1462b0782555354b4480e1f46498586d5882972)
Fixed for 9.5 too.