std::any 包含 std::tuple<std::any> 编译失败

std::any containing std::tuple<std::any> fails to compile

我意识到嵌套 std::any 不是个好主意。然而,我遇到了一些让我抓耳挠腮的事情,我只是想了解为什么编译器会窒息。考虑以下代码行(假设 arg 变量是一个包含另一个 std::any 的 std::any):

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

该行编译得很好。现在,考虑这一行,其中我有一个 std::any 包含一个 std::tuple,其中包含另一个 std::any:

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

现在,编译器崩溃了。这些是我得到的错误:

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),  = (no value),  = (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),  = (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),  = (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);

我很难打开所有这些包并弄清楚哪里出了问题以及如何解决它。

编辑: 我们在评论中发现此代码无法在 G++ 9 及以下版本下编译,但可在 G++ 10 及更高版本上编译,并且在 clang 10 上也失败及以下,但在 clang 11 及更高版本上编译。有人猜到为什么会这样吗?

关键部分错误:no member named 'value' in 'std::is_copy_constructible<std::tuple<std::any> >'

这是编译器抱怨指定对象 std::tuple 不可复制构造的方式。

您的 gcc 显然不相信 std::tuplestd::any 是可复制构造的。如果元组中的所有内容都是可复制构造的,则元组本身应该是可复制构造的。鉴于 std::any 是 C++17,并且 gcc 9 的 C++17 支持不完整,至少在 C++17 的这一部分不完整(gcc 11 的功能列表仍然包含一些 C++17 功能).