考虑以下示例:
template<typename T>
class Base
{
public:
inline void fooBase ()
{
T t; // The following error only occurs when class ABC is not defined at the end of the file: "error: t uses undefined class ABC"
}
protected:
};
class ABC;
class DEF;
class Derived : public Base<ABC>
{
public:
void fooDerived ()
{
DEF def; // error: def uses undefined class DEF
}
};
Derived derived;
void foo ()
{
derived.fooBase ();
}
class ABC {};
class DEF {};
问题
ABC
才能使编译器满意? Derived
或声明全局foo
函数时不需要定义?foo ()
中调用该函数之后,该函数似乎仍被实例化(在文件末尾)。请注意,fooDerived
会产生预期的错误:在使用该类之前,应该(完全)定义该类。
请注意,由于它们是同一问题的完全不同的表达方式,因此不必分别回答所有问题。
经过测试的环境:
DEF def;
之外):https://godbolt.org/z/z_c7mc 答案 0 :(得分:1)
何时实例化模板化类的成员函数?
类模板专门化的成员函数的声明与该类专门化一起被实例化,但是定义仅在需要时被实例化。通常在调用成员函数时。只要不使用成员函数,该定义就可能无法实例化。
您的示例调用成员函数,因此必须实例化定义。
但是,专业化的成员函数可能有多个实例化点。一个在即将使用之前,但在翻译单元的末尾又添加了一个(总是添加)
[温度点] (强调我的意思)
8函数模板的一种特殊化,即成员函数 模板,或类的成员函数或静态数据成员的 模板在一个模板中可能具有多个实例化点 翻译单元,以及实例化要点 如上所述,对于任何具有以下特点的专业化 翻译单元内的实例化,翻译结束 单元也被视为实例化点。专为 一个类模板在一个模板中最多具有一个实例化点 翻译单位。任何模板的专业化可能都有以下几点 在多个翻译单元中实例化。 如果有两个不同的观点 实例化赋予模板专业化不同的含义 根据一定义规则,程序格式错误,没有 需要诊断。
这将我带到下一点,fooBase
在您显示的翻译单元中有两个实例化点。一个ABC
不完整,而另一个var regex = new Regex(@"=\s*(?<Number1>\d*),\s*Num2\s*=\s*(?<Number2>\d*)");
var matches = regex.Match(text);
if(matches.Success)
{
var num1 = Int32.Parse(matches.Groups["Number1"].Value);
var num2 = Int32.Parse(matches.Groups["Number2"].Value);
}
已经完成。在上面的段落下,您的程序格式错误,不需要诊断。编译器可以对违规保持沉默,同时发出似乎可以正常工作的一些代码。但这不能使程序有效。如果将来会更新标准以在这种情况下需要诊断,则非法代码将无法构建。如果编译器希望对其进行诊断,它甚至可能现在失败。