【问题标题】:Why uncalled template class members *parameters* ARE instantiated?为什么未调用的模板类成员 *parameters* 被实例化?
【发布时间】:2013-11-06 06:52:22
【问题描述】:

这个问题与:Why uncalled template class members aren't instantiated? 的对立面,作者很惊讶某些模板方法没有被实例化。

我有相反的问题:当我不希望它们实例化时,我的部分函数正在实例化。采取以下程序:

template <class T> class Foo;

template <class T>
class Bar {
  template <class U> void Baz(typename Foo<T>::X x) {}
};

int main() {
  Bar<int> bar;
}

这个程序编译失败,报错:

test.cc:6:40: error: implicit instantiation of undefined template 'Foo<int>'
  template <class U> void Baz(typename Foo<T>::X x) {}
                                       ^
test.cc:10:12: note: in instantiation of template class 'Bar<int>' requested here
  Bar<int> bar;
           ^
test.cc:2:26: note: template is declared here
template <class T> class Foo;

但是为什么它试图实例化一个我没有调用过的函数的参数呢?它是一个模板函数,带有一个它不知道的模板参数,这使得它实例化函数参数类型变得更加奇怪。

为什么要这样做?为什么 SFINAE 在这里没有帮助我,最坏的情况是从考虑中消除了超载?

【问题讨论】:

  • 作为一个数据点,如果函数没有 ::X 依赖类型,并且只有 void Baz(Foo&lt;T&gt; x),则编译时不会尝试实例化 Foo

标签: c++ templates sfinae


【解决方案1】:

当您创建模板类的实例时,需要完全定义该类。这包括成员函数声明。如果其中一个成员函数声明未完全定义,则该类本身未完全定义。

在这种情况下,Foo&lt;T&gt;::X 没有定义,所以Baz 函数不能完全声明,并且整个类也没有完全定义。

【讨论】:

  • 模板类的实例不需要定义其所有成员。试试template &lt;typename T&gt; struct S { void f() { T t = 0; } void g() { } }; int main() { S&lt;void&gt;().g(); },它编译和运行没有问题,但按照你的逻辑不应该。
  • 将第二句和第三句中的'definitions'改为'declarations',这个答案就正确了。
  • 这并没有真正解释是什么让函数参数与函数体不同(我链接的问题表明你所说的对于函数 bodies 是不正确的)。它也没有解释为什么 SFINAE 在这里不起作用。
  • @hvd S 结构不仅完全由自身定义,其成员函数也完全声明。虽然 S::f 由于使用了 void 类型而无法调用,但它仍然是完全声明的。
  • @JoshHaberman 根据 Chris Dodd 的提示,我已经更改了答案的措辞。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多