一般情况下,哪些情况需要模板参数完整

What are the cases in general which require template argument to be complete?

本文关键字:参数 情况 情况下      更新时间:2023-10-16

考虑简单的代码:

struct x;
template<typename> void func(){}
int main() {
    func<x>();
    return 0;
}

上面的代码不需要类x是完整的,还有其他情况不需要x是完整的吗。一般来说,哪些情况需要模板参数完整?

如果某些模板实例化导致生成要求类型完整的代码,则模板参数必须是完整的类型,例如,任何需要模板大小的构造——参数、成员访问的使用等。

在您的情况下,根本不使用模板参数。任何实例化都不要求类型完整。我们很容易造成错误:

struct x;
template<typename T> void func()
{ T a; } //requires complete type
int main() {
    func<x>();
}

GCC表示:

错误:"x a"具有不完整的类型

如果我们使用指针或引用,则不需要完整的类型:

template<typename T> void func()
{ T* a; } //does not need complete type

请注意,该类型需要在实例化时完成。这意味着,只要您在模板中的使用和该模板的实例化之间定义了结构,就可以了。这编译得很干净:

struct x;
template<typename T> void func()
{ T a; } //requires complete type
struct x{}; //we now define x
int main() {
    func<x>(); //instantiation
}

请注意,模板类的成员函数只有在使用时才会实例化。因此,您可以使用具有成员函数的模板类,该成员函数需要具有不完整模板参数的完整类型,只要您不使用这些成员函数。

例如,使用此代码:

struct x;
template <typename T>
struct Foo {
    void bar() {
    }
    void baz() {
        T a;   
    }
};

这是有效的:

Foo<x> a;
a.bar();

但这不是:

Foo<x> a;
a.baz(); //requires complete type

要求x是指需要知道x在内存中的布局的任何情况。例如:

struct x;
template<typename> void func() {
    // Compiler error: what is x::foo ???
    std::cout << x.foo() << std::endl;
}
int main() {
    func<x>();
    return 0;
}

这和其他地方都一样:如果

  • 您只使用指向类型的指针
  • 或引用
  • 或将其用作声明中的参数

而不使用指针/引用来访问成员。

相关文章: