gcc 什么时候编译未使用的模板代码?

When does gcc compile unused template code?

本文关键字:代码 什么时候 编译 未使用 gcc      更新时间:2023-10-16

我有以下(诚然是人为的)代码,在 gcc 6 中编译得很好,但在 gcc 7 中无法编译。请注意在bar的定义中使用未声明的构造函数。如果该函数在代码中的其他地方被引用,这应该会打印错误(取消注释foo.bar()会导致 gcc 6 打印错误)。但是,即使未使用该函数,gcc 7 也会打印错误。

一些更改导致代码也使用 gcc 7 编译(例如,如果在A的定义中将B替换为T),而一些更改会导致代码在 gcc 6 中失败(例如,如果不使用this->)。这是怎么回事?gcc 什么时候决定编译未使用的模板代码?不同版本的 gcc 是否使用不同的规则来决定?

struct B {};
template <typename T>
struct A {
B* bar()
{
// undeclared constructor
return new B(this->b);
}
B* b;
};
int main (int argc, char* argv[])
{
A<int> foo;
//foo.bar();
}

A::bar()是模板类中的非模板成员函数。 如果它本身是一个模板,SFINAE 将允许代码在不调用时编译bar()。 但是你现在的方式是,一旦A被一些模板参数实例化,所有这些都应该是有效的。

一种解决方案是:

template <typename T>
struct A {
template <typename X>
X* bar()
{
// static_assert(is_same<X, B>) if you want
return new X(this->b);
}
B* b;
};

然后你会调用a.bar<B>()而不是a.bar(),如果你不调用它,它不会被实例化,也不会导致错误。

也许我错过了一些东西,但您似乎正在尝试从 B 指针构造 B 对象。并且没有默认构造函数可以做到这一点。所以你肯定想要:

struct B {
B( B * b ) {
}
};