有没有办法避免模板好友声明的外部可见性?

时间:2014-04-02 13:25:27

标签: c++ templates

看看下面的例子:

A.H:

class A {
protected:
  template<class T>
  friend void b();
};

b.h:

template<class T>
void b() {}

main.cxx:

#include "a.h"

int main()
{
  b<double>();
}

请注意,我忘了包含&#34; b.h&#34;在主文件中。不幸的是,编译器在A类中获取了友元声明并编译了main函数而没有抱怨。我留下了一个神秘的链接错误,这是令人惊讶的,因为实例化应该发生在main.cxx中:

[joel@fedora-joel friend]$ g++ main.cxx 
/tmp/ccfpaeHw.o: In function `main':
main.cxx:(.text+0x5): undefined reference to `void b<double>()'
collect2: error: ld returned 1 exit status

我的问题是:编译器为什么允许这样做?有没有办法对付它?

1 个答案:

答案 0 :(得分:4)

ISO / IEC 14882:2003,§11.4,第3段说明了这一点:

  

首先在朋友声明中声明的函数具有外部链接(3.5)。否则,该函数将保留其先前的链接(7.1.1)。

因此,朋友声明兼作函数声明。这允许main调用该函数,因此没有编译器错误。

发生链接器错误,因为声明没有匹配的函数定义。

我没有办法避免这种行为(因为标准规定了它)。这也是有道理的,因为无论如何都需要函数声明来使友元声明有效(否则你有一个未声明函数的朋友声明)。因此,如果友元声明不会作为函数声明加倍,则必须以其他方式提供函数声明(通过包含适当的标题,例如。)。