在看到这个问题后When is a C++ template instantiation type checked?,并且在相当长的一段时间内对自己感到奇怪,我开始使用代码来吸收知识。答案给出了明确和正确的解释。它提到了两阶段名称查找以及翻译单元结束也被视为功能模板实例化的事实。但是,当使用自动返回类型推导时,我观察到不同的行为:
这就像原始代码一样。这是正确的,并按照链接帖子中的解释工作:
class A;
class B;
template <class T> auto foo() -> T * {
A *pa = nullptr; // ignore pa being `nullptr`.
return static_cast<T *>(pa);
}
auto test() { return foo<B>(); }
class A {};
class B : public A {};
对模板foo
使用自动退货类型扣除时,A
和B
的定义必须出现在foo
的实例化点之前:
不工作:
class A;
class B;
template <class T> auto foo() { // automatic return type deduction
A *pa = nullptr;
return static_cast<T *>(pa);
}
auto test() { return foo<B>(); }
class A {};
class B : public A {};
gcc(4.9和5.2.1)的错误:
错误:从类型'A *'到类型'B *'
的static_cast无效
Clang给出了类似的错误
工作:
class A;
class B;
template <class T> auto foo() { // automatic return type deduction
A *pa = nullptr;
return static_cast<T *>(pa);
}
class A {};
class B : public A {};
auto test() { return foo<B>(); }
为什么会这样?为什么关于编译单元的结束被认为是实例化点的规则不会使模板实例化成为合法的呢?