1

I realize nested std::any's are a bad idea. Nevertheless, I encountered something that's making me scratch my head and I'm just trying to understand why the compiler is choking. Consider the following line of code (assuming that the arg variable is a std::any containing another std::any):

auto result = std::any_cast<std::any>(arg);

That line compiles just fine. Now, consider this line, where I have a std::any containing a std::tuple that contains another std::any:

auto result = std::any_cast<std::tuple<std::any>>(arg);

Now, the compiler blows up. These are the errors I get:

In file included from /home/james/git/trogdor-pp/src/core/event/triggers/luaeventtrigger.cpp:1:
In file included from /home/james/git/trogdor-pp/src/core/include/trogdor/game.h:5:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:37:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/new:40:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/exception:144:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/nested_exception.h:40:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/move.h:55:
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:132:31: error: no member named 'value' in 'std::is_copy_constructible<std::tuple<std::any> >'
    : public conditional<_B1::value, _B2, _B1>::type
                         ~~~~~^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:170:17: note: in instantiation of template class 'std::__and_<std::is_copy_constructible<std::tuple<std::any> >, std::is_constructible<std::tuple<std::any>, const std::tuple<std::any> &> >' requested here
      enable_if<__and_<is_copy_constructible<_Tp>,
                ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:175:5: note: in instantiation of template type alias '__any_constructible' requested here
    using __any_constructible_t =
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:181:56: note: in instantiation of template type alias '__any_constructible_t' requested here
              __any_constructible_t<_Tp, _ValueType&&> = true,
                                                       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:183:7: note: while substituting prior template arguments into non-type template parameter [with _ValueType = const std::tuple<std::any> &, _Tp = std::tuple<std::any>, _Mgr = std::any::_Manager_external<std::tuple<std::any> >]
      any(_ValueType&& __value)
      ^~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:884:56: note: while substituting deduced template arguments into function template 'any' [with _ValueType = const std::tuple<std::any> &, _Tp = (no value), _Mgr = (no value), $3 = (no value), $4 = (no value)]
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                                                       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:884:32: note: (skipping 2 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                               ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:908:14: note: in instantiation of template class 'std::__is_copy_constructible_impl<std::tuple<std::any>, true>' requested here
    : public __is_copy_constructible_impl<_Tp>
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:109:14: note: in instantiation of template class 'std::is_copy_constructible<std::tuple<std::any> >' requested here
    : public conditional<_B1::value, _B1, _B2>::type
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:358:16: note: in instantiation of template class 'std::__or_<std::is_reference<std::tuple<std::any> >, std::is_copy_constructible<std::tuple<std::any> > >' requested here
      { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
               ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:481:26: note: in instantiation of function template specialization 'std::any::__is_valid_cast<std::tuple<std::any> >' requested here
      static_assert(any::__is_valid_cast<_ValueType>(),
                         ^
/home/james/git/trogdor-pp/src/core/event/triggers/luaeventtrigger.cpp:42:32: note: in instantiation of function template specialization 'std::any_cast<std::tuple<std::any> >' requested here
               auto arg = std::any_cast<std::tuple<std::any>>(a);
                               ^
In file included from /home/james/git/trogdor-pp/src/core/event/triggers/luaeventtrigger.cpp:1:
In file included from /home/james/git/trogdor-pp/src/core/include/trogdor/game.h:5:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:37:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/new:40:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/exception:144:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/nested_exception.h:40:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/move.h:55:
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:137:31: error: no member named 'value' in 'std::is_copy_constructible<std::tuple<std::any> >'
    : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
                         ~~~~~^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:150:37: note: in instantiation of template class '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> > > >' requested here
    inline constexpr bool __and_v = __and_<_Bn...>::value;
                                    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:192:27: note: in instantiation of variable template specialization '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> > > >' requested here
              enable_if_t<__and_v<is_copy_constructible<_Tp>,
                          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:196:7: note: while substituting prior template arguments into non-type template parameter [with _ValueType = const std::tuple<std::any> &, _Tp = std::tuple<std::any>, _Mgr = std::any::_Manager_external<std::tuple<std::any> >]
      any(_ValueType&& __value)
      ^~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:884:56: note: while substituting deduced template arguments into function template 'any' [with _ValueType = const std::tuple<std::any> &, _Tp = (no value), _Mgr = (no value), $3 = (no value)]
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                                                       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:884:32: note: while substituting deduced template arguments into function template 'tuple' [with _Dummy = (no value), $1 = (no value)]
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                               ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:902:14: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
    : public is_constructible<_Tp, const _Tp&>
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:908:14: note: in instantiation of template class 'std::__is_copy_constructible_impl<std::tuple<std::any>, true>' requested here
    : public __is_copy_constructible_impl<_Tp>
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:109:14: note: in instantiation of template class 'std::is_copy_constructible<std::tuple<std::any> >' requested here
    : public conditional<_B1::value, _B1, _B2>::type
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:358:16: note: in instantiation of template class 'std::__or_<std::is_reference<std::tuple<std::any> >, std::is_copy_constructible<std::tuple<std::any> > >' requested here
      { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
               ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/any:481:26: note: in instantiation of function template specialization 'std::any::__is_valid_cast<std::tuple<std::any> >' requested here
      static_assert(any::__is_valid_cast<_ValueType>(),
                         ^
/home/james/git/trogdor-pp/src/core/event/triggers/luaeventtrigger.cpp:42:32: note: in instantiation of function template specialization 'std::any_cast<std::tuple<std::any> >' requested here
               auto arg = std::any_cast<std::tuple<std::any>>(a);

I'm having a hard time unpacking all of that and figuring out what's wrong and how I can fix it.

EDIT: we've discovered in the comments that this code does not compile under G++ 9 and below, but compiles on G++ 10 and above, and also fails on clang 10 and below, but compiles on clang 11 and above. Does anybody have any guesses as to why this might be the case?

Crankycyclops
  • 552
  • 5
  • 25
  • Shot in the dark: did you `#include `? – alter_igel Dec 06 '20 at 00:50
  • @alter igel I did. – Crankycyclops Dec 06 '20 at 00:56
  • Can you provide a [mcve]? [It works fine for me](https://godbolt.org/z/nM6q1r) – Kevin Dec 06 '20 at 00:58
  • @Kevin, when I try to compile your example with g++ 8.4, I get this error: test.cpp:7:25: error: conversion from ‘std::tuple’ to non-scalar type ‘std::any’ requested and gcc 9.1 throws a bunch of other errors. – Crankycyclops Dec 06 '20 at 01:03
  • @Crankycyclops Hmm you're right. It gives me the same set of errors as you have in your question for gcc 9.3 too. Maybe those earlier versions didn't fully support `std::any` yet? – Kevin Dec 06 '20 at 01:07
  • @Kevin it's possible. I should try compiling my code under a later version of g++ and see what happens. – Crankycyclops Dec 06 '20 at 01:07
  • Interestingly, it also fails to compile on clang 10 and below, but compiles just fine on clang 11. – Crankycyclops Dec 06 '20 at 01:11
  • 1
    The key part is `error: no member named 'value' in 'std::is_copy_constructible >'` -- your gcc does not believe, apparently, that `std::tuple` is copy-constructible. A tuple, in of itself, should be copy constructible if everything in the tuple is copy-constructible. Given that `std::any` is C++17, the most likely answer is that gcc 9's C++17 support is incomplete. – Sam Varshavchik Dec 06 '20 at 01:28
  • I'm not sure why you edited the question. That seems to be the answer: the needed features for the code to work were only added in those compiler versions. – cigien Dec 06 '20 at 02:48
  • @Sam Varshavchick, if you post that as an answer, I'll accept it as the answer for this question. That's exactly what I was trying to understand. Thank you! – Crankycyclops Dec 06 '20 at 03:49

1 Answers1

2

The key part is error: no member named 'value' in 'std::is_copy_constructible<std::tuple<std::any> >'

This is the compiler's way of complaining that the indicated object, the std::tuple, is not copy-constructible.

Your gcc does not believe, apparently, that std::tuplestd::any is copy-constructible. A tuple, in of itself, should be copy constructible if everything in the tuple is copy-constructible. Given that std::any is C++17, and gcc 9's C++17 support is incomplete, at least incomplete insofar as this part of C++17 goes (gcc 11's feature list still includes some C++17 features).

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148