有没有办法避免模板友元声明的外部可见性
Is there a way to avoid the outside visibility of template friend declarations?
请看下面的例子:
啊:
class A {
protected:
template<class T>
friend void b();
};
BH:
template<class T>
void b() {}
主.cxx:
#include "a.h"
int main()
{
b<double>();
}
请注意,我忘了在主文件中包含"b.h"。不幸的是,编译器在类 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
我的问题是:为什么编译器允许这样做?有没有办法反对它?
ISO/IEC 14882:2003, §11.4, 第 3 段是这样说的:
首先在友元声明中声明的函数具有外部链接 (3.5)。否则,该函数将保留其先前的链接 (7.1.1)。
因此,友元声明兼作函数声明。这允许main
调用该函数,因此没有编译器错误。
发生链接器错误的原因是声明没有匹配的函数定义。
我看不到避免这种行为的方法(因为标准规定了它)。这也是有道理的,因为无论如何都需要函数声明才能使朋友声明有效(否则你会有一个未声明函数的朋友声明)。因此,如果友元声明不能兼作函数声明,则必须以其他方式提供函数声明(通过包含适当的标头,例如)。
相关文章:
- 如何在嵌套类中正确使用友元声明?
- 将子类方法声明为基类的友元
- 在将函数声明为友元时,尖括号的含义是什么?
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- C++ 17 个友元函数声明和内联命名空间
- 将派生类的构造函数声明为父类的友元
- 为什么 gcc 无法从其前向声明中检测到友元类命名空间?
- 类模板中文本运算符的友元声明
- 以嵌套类为参数的友元模板声明
- 模板和隐式构造函数的类定义之外的友元声明
- 如何将友元声明用于具有约束的模板类
- 为什么我不能定义一元运算符,然后在 MSVC 的模板类中声明具有相同名称的友元二进制运算符?
- 为什么在定义类之前声明类的对象会在友元类中给出错误,而在友元函数中不会出错
- 如何将模板友元函数声明为可变参数类
- 嵌套友元类所需的前向声明
- 在派生类或基类中,我应该在哪里声明友元类
- 类定义交叉引用时如何声明友元方法
- 在此范围内未声明友元函数错误
- GCC声明友元函数是重载的,有歧义调用,clang编译
- 声明友元函数时出现变量作用域错误