当前位置: 首页 > 知识库问答 >
问题:

类模板成员函数的显式实例化声明是否会导致类模板的实例化?

丁良骏
2023-03-14

[dcl.spec.auto]/14国[强调我的]:

显式实例化声明不会导致使用占位符类型声明的实体的实例化,但也不会阻止根据需要对该实体进行实例化以确定其类型。[示例:

template <typename T> auto f(T t) { return t; }
extern template auto f(int);    // does not instantiate f<int>
int (*p)(int) = f;              // instantiates f<int> to determine its return type, but an explicit
                                // instantiation definition is still required somewhere in the program

-结束示例]

和[temp.explicat]/11声明[强调我的]:

template <class T>
struct Foo {
    static const auto& foo() { static T t; return t; }
};

// explicit instantiation declarations
extern template const auto& Foo<void>::foo();
extern template const auto& Foo<int>::foo();

int main() {}

现在,考虑我们是否在类模板foo中的friend声明中定义了friend函数:

template <class T>
struct Foo {
    static const auto& foo() { static T t; return t; }
    friend void bar() { }
};
void bar();

如果在同一翻译单元中实例化了foo的多个专门化,则将违反[basic.def.odr]/1:

任何翻译单元不得包含任何变量、函数、类类型、枚举类型或模板的一个以上定义。

template <class T>
struct Foo {
    static const auto& foo() { static T t; return t; }
    friend void bar() { }
};
void bar();

extern template const auto& Foo<void>::foo();
extern template const auto& Foo<int>::foo();

int main() {}

铿锵

错误:重新定义条形图

注意:在实例化模板类foo 时,此处请求:extern template const auto&foo ::foo();

但是我从来没有请求(或者afaict使用这些专门化的方式)将foo foo 专门化实例化。

因此,对于这个问题:

  • 上面的程序(与朋友一起)是格式良好的吗?还是编译器实例化类模板专门化并随后拒绝该程序是正确的?

(1)注意,即使foo()没有使用占位符类型声明,同样的问题(和编译器行为)也适用,但是我们将无法依赖[dcl.spec.auto]/14的明确性,但我们可能不需要。

(2)由于在friend声明中定义的friend是内联的,我们实际上可能会在不同的翻译单元中实例化不同的专门化,并且仍然尊重ODR,但这与本讨论无关。

共有1个答案

阎丰
2023-03-14

类模板必须实例化的论点是,声明匹配可能需要知道关于类的明显需要实例化的事情。考虑简化的示例

template<class T>
struct A {void f(T) {}};

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

要知道成员函数是否存在,我们必须在类模板中实例化声明,通常我们不能在不实例化整个类的情况下这样做:参数类型可能依赖于类模板中的任何其他声明,我们可能需要考虑多个重载,甚至需要进行模板参数推导,以确定f是指哪个f。人们可以争辩说,只有当这些情况中的一种确实存在时,才应该进行实例化,这偏离了CWG2的领域(在那里,实例化显然是不可能的),但其思想是,原则上,为了决定这些问题,实例化是必要的,因为我们只是不尝试首先检查模板本身。

 类似资料:
  • 是否有人知道此显式特化是否有效: clang 主干 (12/3/2013) 给出以下错误: f:...\test.cpp:36:20: 错误: 从类 'O' 中出线定义 “Fun” 没有定义 1生成错误。 任何来自标准的支持参考来证明你的答案将不胜感激! 注意:我有点惊讶这是一个错误——我认为应该为任何以< code >开始实例化“Fun”的模板参数族选择专门化 这是一个叮当的错误还是我期望中的错

  • 我正在从事一个C语言的项目,当我显式实例化模板类时,很难理解模板类的哪些成员被显式实例化。我编写了以下文件,然后使用Visual C 2008 Express Edition的发布配置编译该文件,然后将其放入反汇编程序。 忽略这个文件目前并不真正需要模板,这可以很好地编译。我将exe放入反汇编程序,它告诉我该测试 这导致测试

  • 根据我的尝试和错误,答案似乎是否定的,这是一个简单的 将为班上的所有成员工作。然而,我读过的代码建议不是这样,如果能给出具体的答案,我将不胜感激。

  • 这有什么问题: 我在这里尝试过:用不同的编译器https://godbolt.org/z/NkL44s: x86-64 gcc 9.2:编译 x86-64 gcc(主干):失败 x86-64 clang 6.0.0:编译 x86-64 clang 7.0.0及更高版本:失败 x64 msvc v19.22:编译 x64 msvc v19.23(内部测试):失败 那么,为什么最近的编译器会拒绝这一点

  • 我有一个模板化的C++类,它也有一个模板化的成员函数。这个成员函数的模板参数以特定的方式依赖于类的模板参数(请参阅下面的代码)。我正在为其模板参数的两个不同值实例化(而不是专门化)该类。一切都在这一点上进行。但是,如果我调用模板化的成员函数,对第一个实例化对象的调用只会编译,而不会编译第二个。似乎编译器没有为模板类的第二次实例化实例化模板化成员函数。我正在使用“g++filename.cpp”编译

  • 我有一个类模板和一个函数模板定义了一个,它引用要绑定到的模板类型。 我想要的是将< code>make_obj函数声明为< code>friend,这样它可以创建< code>Obj的,但是其他人不能(除了通过copy ctor)。 我尝试了几个朋友声明,包括 和 后者是使< code>make_obj的所有模板实例化成为< code>Obj类的朋友的不太理想的尝试。然而,在这两种情况下,我得到相