【发布时间】:2020-02-21 17:29:05
【问题描述】:
编译(使用 GCC 9 和 Clang 9 测试):
template<typename U>
struct inherit : U { };
int test(inherit<int> arg);
但这不是:
int test(inherit<int> arg) { }
为什么第一个会编译?
【问题讨论】:
-
请同时分享您收到的第二个 sn-p 的编译错误。
编译(使用 GCC 9 和 Clang 9 测试):
template<typename U>
struct inherit : U { };
int test(inherit<int> arg);
但这不是:
int test(inherit<int> arg) { }
为什么第一个会编译?
【问题讨论】:
int test(inherit<int> arg); 只是一个声明。因此,我们还不需要知道inherit<int>。因此,编译器会放手。
有了int test(inherit<int> arg) { },你现在有了一个定义,现在我们需要知道inherit<int>,所以arg可以在函数退出时被销毁。此时模板被实例化,您会收到一个错误,因为它是无效的。
忽略该声明的另一个原因是 inherit 稍后可能会专门化为 int 并且该专业化实际上可能是一个有效的类,因为您可以拥有类似的东西
template<>
struct inherit<int> { };
如果您要在 int test(inherit<int> arg); 和 int test(inherit<int> arg) { } 之间添加它,那么代码现在可以编译,因为 inherit<int> 现在是一个有效类型。
【讨论】:
inherit 中放入 using type = int; 并执行 int test(inherit<int>::type arg);)以便编译器实例化模板?
inherit<int>::type 是什么,它必须实例化 inherit<int>。
我希望其他人能解释原因。我将在这里使用现象学方法;)。
一旦您实际实例化 inherit<int>,您的第一个版本也无法编译:
int main() {
test( inherit<int>{} );
}
错误:
prog.cc: In instantiation of 'struct inherit<int>':
prog.cc:9:24: required from here
prog.cc:4:8: error: base type 'int' fails to be a struct or class type
4 | struct inherit : U { };
| ^~~~~~~
我本可以简单地尝试创建一个inherit<int> 对象(不调用test)来得到类似的错误。
另一方面,这只是一个声明:int test(inherit<int> arg);,因此在实际提供定义之前,可以对 inherit 进行专门化,这样我们也可以为 test 提供有效定义:
template<typename U>
struct inherit : U { };
// looks broken
int test(inherit<int> arg);
// but that this point we dont really know yet what `inherit<int>` really is
// whoops inherit<int> is something different now
template <> struct inherit<int> {};
// ... and now this is completely fine
int test(inherit<int> arg) {}
int main() {
test( inherit<int>{} );
}
【讨论】: