我希望下面的代码无法编译,因为asf的成员函数没有提供所需的成员。实际上,即使关闭优化,它在不使用时也可以很好地编译。这怎么可能?Exclamator<B>Bnamef
#include <string>
#include <iostream>
class A {
public:
std::string name() { return "A"; }
};
class B {} ;
template <typename T>
class Exclamator {
public:
Exclamator(T a): x{a} {}
void f() {
std::cout << x.name() << std::endl;
}
private:
T x;
};
int main() {
A a;
Exclamator xa {a};
xa.f();
B b;
Exclamator xb {b};
// xb.f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
$ g++ -std=c++17 -O0 main.cpp
$ ./a.out
A
Run Code Online (Sandbox Code Playgroud)
这是可能的,因为 C++ 标准实际上需要这种行为。模板类的方法仅在使用时才会被实例化。您可以声明此模板类的实例,但在某些内容引用特定方法之前,它并不真正“存在”。模板方法仍然必须具有有效的语法,但在实例化之前,它处于一种不确定状态。这允许模板类包含仅当使用特定类实例化模板时格式良好的方法。大多数时候,有必要专门化一个模板类,以获得额外的方法或失去其他方法。但是,有时,无需专业化,通过这种方法就可以逃脱惩罚。
这对于 C++ 来说至关重要且基础。如果您浏览一个好的 C++ 参考站点,您会注意到许多构造函数和其他模板类方法都被注释为仅当满足某些特定条件时它们“参与重载解析”。这是使这一切成为可能的(部分)原因。