gpt4 book ai didi

c++ - 使用 `extern template` 防止模板类的隐式实例化

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:17:56 24 4
gpt4 key购买 nike

考虑以下代码片段:

template <typename>
struct X { };

extern template struct X<int>;

int main()
{
X<int>{};
}

它编译并链接:live example on godbolt.org .由于 extern template 声明,我希望它不会链接。

我的理解是 extern template 的意思是:“请不要在这个 TU 中实例化这个特定的模板特化,它将由其他一些 TU 提供,你可以链接到它” .

示例/描述。我在 isocpp 上看到过,cppreference 似乎验证了我的心智模型。例如

From https://en.cppreference.com/w/cpp/language/class_template:

An explicit instantiation declaration (an extern template) skips implicit instantiation step: the code that would otherwise cause an implicit instantiation instead uses the explicit instantiation definition provided elsewhere (resulting in link errors if no such instantiation exists). This can be used to reduce compilation times by explicitly declaring a template instantiation in all but one of the source files using it, and explicitly defining it in the remaining file.

为什么我的代码片段链接?这里到底发生了什么?


编辑 - 在最新的标准草案中找到这个:

[temp.explicit]

If an entity is the subject of both an explicit instantiation declaration and an explicit instantiation definition in the same translation unit, the definition shall follow the declaration. An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation in the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required.

这是否意味着我发布的代码片段格式错误,NDR

最佳答案

Why does my code snippet link? What is actually happening here?

好吧,没有任何链接。因为必须考虑显式实例化的影响。来自 n3337:

[temp.explicit] (emphasis mine)

10 Except for inline functions and class template specializations, explicit instantiation declarations have the effect of suppressing the implicit instantiation of the entity to which they refer. [ Note: The intent is that an inline function that is the subject of an explicit instantiation declaration will still be implicitly instantiated when odr-used ([basic.def.odr]) so that the body can be considered for inlining, but that no out-of-line copy of the inline function would be generated in the translation unit. — end note ]

所以类模板特化的隐式实例化X<int> , 没有被压制。它也是一个聚合,所以它的初始化是内联的,我们没有任何链接。但是,如果它有任何成员,这些在段落8 下被隐藏。 :

An explicit instantiation that names a class template specialization is also an explicit instantiation of the same kind (declaration or definition) of each of its members (not including members inherited from base classes) that has not been previously explicitly specialized in the translation unit containing the explicit instantiation, except as described below.

因此,如果您有类似这样的东西而不是聚合:

template <typename>
struct X {
X();
};

template <typename T>
X<T>::X() {}

extern template struct X<int>;

int main()
{
X<int>{};
}

如您所料,那会失败,因为它 ODR 使用其定义从未实例化的构造函数。声明 实例化的,因为封闭的特化是实例化的,如上所述。但是在显式实例化声明的抑制作用下,我们永远得不到任何定义。

关于c++ - 使用 `extern template` 防止模板类的隐式实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56448493/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com