【问题标题】:Why does the compiler instantiate templates while I ask him not to?为什么编译器实例化模板,而我要求他不要?
【发布时间】:2021-12-30 05:42:08
【问题描述】:

我想防止编译器使用extern template 隐式实例化某些模板。

以下 sn-ps 按预期工作(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-tracetemplight++观察显着的编译时间来检查)。

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

谢谢!

【问题讨论】:

  • static_assert(sizeof(T) == 0); 类似于 static_assert(false); 使模板格式不正确的 NDR。
  • 编译器必须在模板中做一些检查,即使没有实例化。
  • @jarod 我不确定static_assert(sizeof(T) == 0); 是否与static_assert(false); 相同,因为它取决于类型。 static_assert 不会为第一个 sn-p 触发,但它会触发 static_assert(false);
  • 它仍然是格式错误的 NDR。只是使表达式依赖使编译器更难诊断。
  • @jarod 我觉得编译器在我的实际案例中所做的不仅仅是一些检查:给定模板所花费的时间(用 -ftime-trace 测量)在显式实例化的地方与在编译器隐式实例化模板,而被要求不要

标签: c++ c++11 templates compilation template-instantiation


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 2015-07-25
    • 2019-12-18
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多