我从一个基类派生,在其中尝试定义一个类型。该类型通过变体依赖于自身,因此需要在定义时了解基类的内存布局。但是,我不是过早地定义了类型吗?所以我认为这会起作用,但事实并非如此(CompilerExplorer):
#include <variant>
#include <cstddef>
#include <array>
template <size_t V> struct container_base;
template <size_t V> struct container;
template <size_t V>
using val = std::variant<std::monostate, int, container_base<V>>;
template <size_t V>
struct container_base
{
using iterator = typename std::array<val<V>, V>::iterator;
};
template <size_t V>
struct container : public container_base<V>
{
};
int main()
{
container<100> A;
}
这产生:
In file included from /opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/variant:37,
from <source>:1:
/opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/type_traits: In instantiation of 'struct std::is_copy_constructible<container_base<100> >':
/opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/type_traits:3202:33: required from 'constexpr const bool std::is_copy_constructible_v<container_base<100> >'
/opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/variant:329:5: required from 'constexpr const bool std::__detail::__variant::_Traits<std::monostate, int, container_base<100> >::_S_copy_ctor'
/opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/variant:1334:11: required from 'class std::variant<std::monostate, int, container_base<100> >'
/opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/array:109:55: required from 'struct std::array<std::variant<std::monostate, int, container_base<100> >, 100>'
<source>:15:11: required from 'struct container_base<100>'
<source>:19:8: required from 'struct container<100>'
<source>:25:20: required from here
/opt/compiler-explorer/gcc-trunk-20220726/include/c++/13.0.0/type_traits:1012:52: error: static assertion failed: template argument must be a complete class or an unbounded array
1012 | static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
我的理解是,variant 在第一次使用时需要一个完整的类型才能使用(在 main 中!但直到那时类型才完整,所以我不知道为什么它不起作用。我能做什么解决这个问题吗?
@IgorTandetnik 在评论中回答:
访问
[这是完成类型std::array<val<V>, V>::iterator
所必需的] 需要实例化
container_base<V>
,这需要实例化std::array<val<V>, V>
,这需要实例化
val<V>
,而
std::variant<std::monostate, int, container_base<V>>
此时是一个不完整的类型.
container_base<V>
一个稍微简化的示例,使用
StdArray
和 StdVariant
的存根版本代替 std::array
和 std::variant
,如下:Godbolt。