2

我想防止编译器使用extern template.

以下片段按预期工作(static_assert不触发):

template<typename T>
void f() {
    static_assert(sizeof(T) == 0, "f()");
};

extern template void f<int>();

void g() {
    f<int>();
}

但是有了这个,编译器似乎试图实例化模板函数,因为static_assert确实触发了:

struct S {
    template<typename T>
    void f() {
        static_assert(sizeof(T) == 0, "S::f()");
    } 
};

extern template void S::f<int>();

void g() {
    S s;
    s.f<int>();
}

有了这个,static_assert也会触发,而我希望它不会:

template<typename T>
struct S {
    S(){};
    static_assert(sizeof(T) == 0, "S");
};

extern template struct S<int>;

void g() {
    S<int> s;
}

在我的实际情况中,我想加快编译时间,但我观察到编译有 的翻译单元,extern template ...与这些模板相关的符号不会出现在.o文件中(用 看nm),但它们实际上是编译的。 ..(我通过使用 clang-ftime-trace和 with观察重要的编译时间来检查这一点templight++)。

为什么似乎extern template没有按预期工作?

谢谢!

4

1 回答 1

1

显式实例化声明不能抑制所有实例化:毕竟,必须知道类的成员才能使用该类型的对象,并且内联函数必须知道它们的定义才能内联。

这个例子只是快速连续的两个例子:类模板不能“保护”成员函数模板,并且该成员函数模板是内联的,因为它是在其类中定义的。

后一条规则有点武断:由于 ODR 的原因,它曾经被认为是必要的,但现代理解是整个类(模板)定义的“合并”就足够了。因此,C++20 删除inline了模块中的隐含,它与链接规则交互不良。

于 2021-11-19T15:04:41.397 回答