A::A 未定义行为变体的向量成员吗?

问题描述 投票:0回答:2
#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
类似。

c++ c++17 language-lawyer
2个回答
0
投票

std::vector
通过

0
投票

24.3.12.1.4

如果分配器满足分配器完整性要求,则在实例化向量时可以使用不完整类型 T。 T 应在引用向量专业化结果的任何成员之前完成。

std::optional
不提供此类保证。

© www.soinside.com 2019 - 2024. All rights reserved.