struct A;
template <typename> class Foo { };
Foo<A> foo; // note A is incomplete here
struct A {};
Foo<A>
仅取决于名称A
不是它的完整类型。
所以这是格式良好的;然而,这种事情仍然可能会破坏(变得格式错误),但在您测试的每个编译器中都可以编译。
首先,我们偷做完了 https://stackoverflow.com/a/21121104/1774667。然后我们这样做:
struct A;
template <class T> class Foo {
enum{ value = is_complete<T>::value };
};
Foo<A> foo; // note A is incomplete here
struct A {};
我们还好,尽管如此:
[...] 对于在翻译单元内具有实例化点的任何此类专门化,翻译单元的末尾也被视为实例化点。 [...]
因为该子句不适用于模板类。在这里,模板类的唯一实例化就可以了。
现在,如果在另一个文件中您有:
struct A {};
Foo<A> foo2;
你的程序格式不正确。
但是,在单文件情况下:
struct A;
template <class T> class Foo {
enum{ value = is_complete<T>::value };
};
Foo<A> foo; // note A is incomplete here
struct A {};
Foo<A> foo2; // ill-formed
你的代码很好。有一个实例化点Foo<A>
在给定的编译单元中;第二个是对第一个实例化点的引用。
一个和两个文件版本几乎肯定会在 C++ 编译器中编译,不会出现错误或警告。
有些编译器甚至会记住从一个编译单元到另一个编译单元的模板实例化;Foo<A>
将有一个::value
那是false
即使foo2
已创建(具有完整的A
)。其他人会有两种不同的Foo<A>
每个编译单元中的 s;它的方法将被标记为内联(并且是不同的),类的大小可能不一致,并且您将遇到一连串不良的程序问题。
最后,请注意,许多类型std
要求它们的模板参数在旧版本的 C++ 中是完整的(包括c++11 /questions/tagged/c%2b%2b11:“17.6.4.8 其他函数 (...) 2. 在以下情况下效果未定义:(...) 特别是 - 如果在实例化模板组件时使用不完整类型 (3.9) 作为模板参数,除非特别允许该组件”——复制自 boost 不完整容器文档)。具体来说,std::vector<T>
曾经要求T
是完整的。
By c++17 /questions/tagged/c%2b%2b17具有改变为std::vector https://stackoverflow.com/a/44675477/1774667:
[向量.概述]/3
如果分配器满足分配器完整性要求 17.6.3.5.1,则在实例化向量时可以使用不完整类型 T。 T 应在引用所得向量专业化的任何成员之前完成。
现在,甚至在此之前c++17 /questions/tagged/c%2b%2b17,大多数实现std::vector<T>
不完整也可以T
直到您尝试使用一个方法(包括它的许多构造函数或析构函数),但标准规定T
must是完整的。
This actually gets in the way of some unuseful code, like having a function type that returns vectors of its own type1. Boost https://www.boost.org/doc/libs/1_48_0/doc/html/container/containers_of_incomplete_types.html has a library to solve this problem.
template <typename T>
struct Foo {
Foo() {
new T;
}
};
的身体Foo<T>::Foo()
仅在“被调用时”实例化。所以T
未完成不会产生任何影响,直到Foo::Foo()
叫做。
Foo<A> foo;
^^ 将无法以不完整的方式编译A
.
using foo_t = Foo<A>;
^^ 将编译,并且不会导致任何问题。
using foo_t = Foo<A>;
struct A {};
foo_t foo;
也没有问题。的身体foo_t::foo_t
当我们尝试构造一个时被实例化foo_t
,并且所有定义都匹配。
1 Can you say state machine transition function?