#include <variant>
#include <vector>
struct A;
using B = std::variant<A>;
struct A {
std::vector<B> v;
};
int main() {
A a;
}
它使用 GCC、clang 和 MSVC 进行编译。
当我将
std::vector
替换为 std::optional
时,它不再起作用。
#include <variant>
#include <optional>
struct A;
using B = std::variant<A>;
struct A {
std::optional<B> v;
};
int main() {
A a;
}
clang + libstdc++:
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:40:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3416:7: error: incomplete type 'A' used in type trait expression
3416 | = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:372:5: note: in instantiation of variable template specialization 'std::is_trivially_move_constructible_v<A>' requested here
372 | (is_trivially_move_constructible_v<_Types> && ...);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:377:23: note: in instantiation of static data member 'std::__detail::__variant::_Traits<A>::_S_trivial_move_ctor' requested here
377 | _S_trivial_dtor && _S_trivial_move_ctor
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:759:45: note: in instantiation of static data member 'std::__detail::__variant::_Traits<A>::_S_trivial_move_assign' requested here
759 | _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:762:28: note: in instantiation of template type alias '_Move_assign_alias' requested here
762 | struct _Variant_base : _Move_assign_alias<_Types...>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1362:15: note: in instantiation of template class 'std::__detail::__variant::_Variant_base<A>' requested here
1362 | : private __detail::__variant::_Variant_base<_Types...>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: note: in instantiation of template class 'std::variant<A>' requested here
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:506:12: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<std::variant<A>>' requested here
506 | bool = is_trivially_copy_constructible_v<_Tp>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:704:15: note: in instantiation of default argument for '_Optional_base<std::variant<A>>' required here
704 | : private _Optional_base<_Tp>,
| ^~~~~~~~~~~~~~~~~~~
<source>:9:22: note: in instantiation of template class 'std::optional<std::variant<A>>' requested here
9 | std::optional<B> v;
| ^
<source>:8:8: note: definition of 'A' is not complete until the closing '}'
8 | struct A {
| ^
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:40:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: error: incomplete type 'A' used in type trait expression
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:370:5: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<A>' requested here
370 | (is_trivially_copy_constructible_v<_Types> && ...);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:374:23: note: in instantiation of static data member 'std::__detail::__variant::_Traits<A>::_S_trivial_copy_ctor' requested here
374 | _S_trivial_dtor && _S_trivial_copy_ctor
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:705:45: note: in instantiation of static data member 'std::__detail::__variant::_Traits<A>::_S_trivial_copy_assign' requested here
705 | _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:708:32: note: in instantiation of template type alias '_Copy_assign_alias' requested here
708 | struct _Move_assign_base : _Copy_assign_alias<_Types...>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:762:28: note: in instantiation of template class 'std::__detail::__variant::_Move_assign_base<false, A>' requested here
762 | struct _Variant_base : _Move_assign_alias<_Types...>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1362:15: note: in instantiation of template class 'std::__detail::__variant::_Variant_base<A>' requested here
1362 | : private __detail::__variant::_Variant_base<_Types...>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: note: in instantiation of template class 'std::variant<A>' requested here
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:506:12: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<std::variant<A>>' requested here
506 | bool = is_trivially_copy_constructible_v<_Tp>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:704:15: note: in instantiation of default argument for '_Optional_base<std::variant<A>>' required here
704 | : private _Optional_base<_Tp>,
| ^~~~~~~~~~~~~~~~~~~
<source>:9:22: note: in instantiation of template class 'std::optional<std::variant<A>>' requested here
9 | std::optional<B> v;
| ^
<source>:8:8: note: definition of 'A' is not complete until the closing '}'
8 | struct A {
| ^
In file included from <source>:1:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:276:8: error: field has incomplete type 'A'
276 | _Type _M_storage;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:274:7: note: in instantiation of member class 'std::__detail::__variant::_Uninitialized<A>::(anonymous union at /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:274:7)' requested here
274 | union {
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:434:30: note: in instantiation of template class 'std::__detail::__variant::_Uninitialized<A>' requested here
434 | _Uninitialized<_First> _M_first;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:516:41: note: in instantiation of template class 'std::__detail::__variant::_Variadic_union<false, A>' requested here
516 | _Variadic_union<false, _Types...> _M_u;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:581:30: note: in instantiation of template class 'std::__detail::__variant::_Variant_storage<false, A>' requested here
581 | struct _Copy_ctor_base : _Variant_storage_alias<_Types...>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:618:30: note: in instantiation of template class 'std::__detail::__variant::_Copy_ctor_base<false, A>' requested here
618 | struct _Move_ctor_base : _Copy_ctor_alias<_Types...>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:656:32: note: (skipping 3 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
656 | struct _Copy_assign_base : _Move_ctor_alias<_Types...>
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1362:15: note: in instantiation of template class 'std::__detail::__variant::_Variant_base<A>' requested here
1362 | : private __detail::__variant::_Variant_base<_Types...>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: note: in instantiation of template class 'std::variant<A>' requested here
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:506:12: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<std::variant<A>>' requested here
506 | bool = is_trivially_copy_constructible_v<_Tp>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:704:15: note: in instantiation of default argument for '_Optional_base<std::variant<A>>' required here
704 | : private _Optional_base<_Tp>,
| ^~~~~~~~~~~~~~~~~~~
<source>:9:22: note: in instantiation of template class 'std::optional<std::variant<A>>' requested here
9 | std::optional<B> v;
| ^
<source>:8:8: note: definition of 'A' is not complete until the closing '}'
8 | struct A {
| ^
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:40:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3388:7: error: incomplete type 'A' used in type trait expression
3388 | = __is_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:357:5: note: in instantiation of variable template specialization 'std::is_copy_constructible_v<A>' requested here
357 | (is_copy_constructible_v<_Types> && ...);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1364:43: note: in instantiation of static data member 'std::__detail::__variant::_Traits<A>::_S_copy_ctor' requested here
1364 | __detail::__variant::_Traits<_Types...>::_S_copy_ctor,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: note: in instantiation of template class 'std::variant<A>' requested here
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:506:12: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<std::variant<A>>' requested here
506 | bool = is_trivially_copy_constructible_v<_Tp>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:704:15: note: in instantiation of default argument for '_Optional_base<std::variant<A>>' required here
704 | : private _Optional_base<_Tp>,
| ^~~~~~~~~~~~~~~~~~~
<source>:9:22: note: in instantiation of template class 'std::optional<std::variant<A>>' requested here
9 | std::optional<B> v;
| ^
<source>:8:8: note: definition of 'A' is not complete until the closing '}'
8 | struct A {
| ^
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:40:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3391:7: error: incomplete type 'A' used in type trait expression
3391 | = __is_constructible(_Tp, __add_rval_ref_t<_Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:359:5: note: in instantiation of variable template specialization 'std::is_move_constructible_v<A>' requested here
359 | (is_move_constructible_v<_Types> && ...);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1366:43: note: in instantiation of static data member 'std::__detail::__variant::_Traits<A>::_S_move_ctor' requested here
1366 | __detail::__variant::_Traits<_Types...>::_S_move_ctor,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: note: in instantiation of template class 'std::variant<A>' requested here
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:506:12: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<std::variant<A>>' requested here
506 | bool = is_trivially_copy_constructible_v<_Tp>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:704:15: note: in instantiation of default argument for '_Optional_base<std::variant<A>>' required here
704 | : private _Optional_base<_Tp>,
| ^~~~~~~~~~~~~~~~~~~
<source>:9:22: note: in instantiation of template class 'std::optional<std::variant<A>>' requested here
9 | std::optional<B> v;
| ^
<source>:8:8: note: definition of 'A' is not complete until the closing '}'
8 | struct A {
| ^
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:40:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3385:54: error: incomplete type 'A' used in type trait expression
3385 | inline constexpr bool is_default_constructible_v = __is_constructible(_Tp);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1422:26: note: in instantiation of variable template specialization 'std::is_default_constructible_v<A>' requested here
1422 | variant() requires is_default_constructible_v<__to_type<0>> = default;
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1422:26: note: while substituting template arguments into constraint expression here
1422 | variant() requires is_default_constructible_v<__to_type<0>> = default;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1422:7: note: while checking constraint satisfaction for function 'variant' required here
1422 | variant() requires is_default_constructible_v<__to_type<0>> = default;
| ^~~~~~~
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/type_traits:3413:7: note: in instantiation of template class 'std::variant<A>' requested here
3413 | = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:506:12: note: in instantiation of variable template specialization 'std::is_trivially_copy_constructible_v<std::variant<A>>' requested here
506 | bool = is_trivially_copy_constructible_v<_Tp>,
| ^
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/optional:704:15: note: in instantiation of default argument for '_Optional_base<std::variant<A>>' required here
704 | : private _Optional_base<_Tp>,
| ^~~~~~~~~~~~~~~~~~~
<source>:9:22: note: in instantiation of template class 'std::optional<std::variant<A>>' requested here
9 | std::optional<B> v;
| ^
<source>:8:8: note: definition of 'A' is not complete until the closing '}'
8 | struct A {
| ^
我认为它是有效的,因为所有
std::vector
实现都将数据存储在堆上。但这不是标准所要求的,不是吗?如果我没记错的话,某些 std::vector
实现可能会进行某种小数据优化,使其与 std::optional
类似。
std::vector
通过