为什么使用基本类型作为 base-class 有时会编译?

Why does using a fundamental type as a base-class compile sometimes?

此编译(使用 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 进行专门化,并且该专门化实际上可能是有效的 class,因为您可以拥有类似

template<>
struct inherit<int> { };

如果您要在 int test(inherit<int> arg);int test(inherit<int> arg) { } 之间添加它,那么代码现在可以编译,因为 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 进行专门化,使我们也能够为 [= 提供有效的定义15=]:

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>{} );
}