本文介绍了类模板的成员函数的显式实例化声明是否导致类模板的实例化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[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.explicit]/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() {}

这是格式正确的; [temp.explicit]/11 不适用根据 [dcl.spec.auto]/14 .

This is well-formed; [temp.explicit]/11 does not apply as neither member function of class template specialization entities Foo<void>::foo() nor Foo<int>::foo() are used in a way that would otherwise cause an implicit instantiation, as per [dcl.spec.auto]/14.

现在,考虑是否在类模板Foo中的朋友声明中定义了朋友函数:

Now, consider if we defined a friend function at its friend declaration in the class template Foo:

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

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

If any more than one specialization of Foo is instantiated in the same translation unit, [basic.def.odr]/1 will be violated:

对于实例化的每个专业化,将

作为朋友bar()重新定义.

as the friend bar() would be re-defined for each specialization that is instantiated.

根据上述参数,(类模板的)两个成员函数专门化的显式实例化声明不应导致关联的类模板的任何实例化(按照 [dcl.spec.auto]/14 ),这意味着以下程序的格式也应合理:

According to the argument above, the explicit instantiation declarations of the two member function (of class template) specializations should not lead to any instantiation of the associated class template (as per [dcl.spec.auto]/14), meaning the following program should also arguably be well-formed:

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() {}

但是,Clang(10.0.0)和GCC(10.1.0)都拒绝程序(C ++ 14,C ++ 17,C ++ 2a),并显示"void bar()的重新定义"错误:

However, both Clang (10.0.0) and GCC (10.1.0) rejects the program (C++14, C++17, C++2a) with a "redefinition of void bar()" error:

错误:bar

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

note: in instantiation of template class Foo<int> requested here:extern template const auto& Foo<int>::foo();

海湾合作委员会

struct Foo<int>的实例中:

错误:重新定义void bar()

但是我从来没有要求(或以某种方式使用这些专门知识,以使)实例化Foo<int>Foo<void>专门知识.

But I never requested (or, afaict, used these specializations in a way such that) the Foo<int> or Foo<void> specializations (are) to be instantiated.

问题所在:

  • 上面的程序(和朋友一起)格式是否正确,还是编译器正确地实例化了类模板的专业化知识,并随后拒绝了该程序?

推荐答案

必须实例化类模板的论据是声明 matching 可能需要了解有关类的知识,而这些东西显然需要实例化.考虑简化的例子

The argument that the class template must be instantiated is that declaration matching may need to know things about the class that plainly require instantiation. Consider the simplified example

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

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

要知道成员函数是否存在,我们必须实例化类模板中的声明,并且通常不能在不实例化整个类的情况下做到这一点:参数类型可以依赖于任何其他 >在类模板中进行声明,我们可能需要考虑多个重载,甚至进行模板参数推导来确定是哪个f.有人可以说,只有在其中一种情况确实存在时才应进行实例化,这会误入 CWG2 领域(显然不可能进行实例化),但是其想法是,对于这样的问题,决定原则上需要实例化,因为我们根本不会尝试首先检查模板本身.

To know whether the member function exists, we must instantiate the declaration in the class template, and we can’t do that in general without instantiating the whole class: the parameter type could depend on any other declarations in the class template, and we might need to consider multiple overloads or even do template argument deduction to decide which f is meant. One can argue that instantiation should happen only if one of these situations actually pertains, which strays into CWG2 territory (where instantiation is obviously impossible), but the idea is that instantiation is necessary in principle to decide about such questions because we simply don’t try examining the template itself first.

这篇关于类模板的成员函数的显式实例化声明是否导致类模板的实例化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 18:45