外部模板类和非模板友元函数
Extern template class and non-template friend functions
我已经开始玩extern
模板了,我偶然发现了一个问题,我找不到任何相关信息。假设我有一个带有非模板友元函数的类模板(在类模板声明中定义)。我为类声明了一些extern
模板实例化,但如何将友元函数也声明为extern?
以下是一些示例代码:
// --- test.h ---
template <typename T>
class Foo {
private:
T value;
public:
friend void some_friend_function(Foo<T>& obj) {
obj.value -= T(42);
};
void some_member_function(T rhs) { value += rhs; };
};
extern template class Foo<int>;
//extern void some_friend_function(Foo<int>&); // I tried this also...
// --- test.cpp ---
#include "test.h"
template class Foo<int>;
//void some_friend_function(Foo<int>&); // ... with this.
当我编译上面的(有或没有注释行)时,我只得到以下导出的符号:
0000000000000000 W _ZN3FooIiE20some_member_functionEi
因此,非模板友元函数肯定不会随着类模板的显式实例化而实例化(和extern
'd)。这正常吗?至少,这就是GCC产生的结果(在4.6.3和4.7.2中进行了测试)
有没有什么方法可以让friend函数标记为extern?我知道这不是一个大问题,因为我可以很高兴地接受根据需要实例化的朋友函数(即非外部函数),但我很想知道是否有办法做到这一点,如果没有,这是疏忽还是故意的?
EDIT:显而易见的解决方案
我的问题特别是关于非模板朋友函数,而不是关于找到一个解决方法来避免这个问题,这是微不足道的。第一个明显的解决方法是:
template <typename T>
class Foo {
private:
T value;
public:
template <typename U>
friend void some_friend_function(Foo<U>& obj) {
obj.value -= T(42);
};
};
extern template class Foo<int>;
extern template void some_friend_function(Foo<int>&);
// --- in cpp file: ---
template class Foo<int>;
template void some_friend_function(Foo<int>&);
另一个匹配更紧密但更麻烦的是:
template <typename T> class Foo; // forward-declare.
template <typename T>
void some_friend_function(Foo<T>&); // declaration.
template <typename T>
class Foo {
private:
T value;
public:
friend void some_friend_function<>(Foo<T>& obj); // befriend the T-specialization.
};
template <typename T>
void some_friend_function(Foo<T>& obj) { // definition.
obj.value -= T(42);
};
extern template class Foo<int>;
extern template void some_friend_function(Foo<int>&);
// --- in cpp file: ---
template class Foo<int>;
template void some_friend_function(Foo<int>&);
"外部模板类"的作用是声明显式实例化可用。显式实例化声明的效果不适用于内联函数或模板专业化(14.7.2[temp.extic]第10段):
除了内联函数和类模板专门化之外,显式实例化声明具有抑制其引用的实体的隐式实例化的效果。
由于类定义中的friend
函数定义必然是inline
函数,因此它将保持inline
函数独立于模板的显式实例化声明(而且,正如您正确指出的,它不是模板,也不遵循模板实例化规则)。
相关文章:
- C++模板来检查友元函数的存在
- 如何使用单独文件中的派生类访问友元函数对象
- 模板化的类和友元函数
- 友元函数无法访问私有数据成员 (c++)
- 继承和友元函数,从基类访问受保护的成员
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 在模板类之外定义友元函数的正确方法是什么?
- 2个模板化类的非模板友元函数未定义引用错误
- C++ 友元函数和私有构造函数
- 使第二个类的构造函数成为第一个类中的友元函数
- 未定义的类模板不会实例化以检查友元函数
- C++类中的友元函数有问题?
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 模板类中的模板友元函数
- C++ 17 个友元函数声明和内联命名空间
- 友元函数需要一个帮助程序函数
- 在类内定义的友元函数与类外定义的友元函数的查找规则之间的差异
- 运算符重载在 C++ 中使用友元函数
- 类C++友元函数无法访问封装的类
- 函数指针作为友元函数