我开始使用extern
模板了,我偶然发现了一个我无法找到相关信息的问题。假设我有一个带有非模板友元函数的类模板(在类模板声明中定义)。我为类声明了一些extern
模板实例,但是如何将friend函数声明为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上测试)。
有什么方法可以让朋友的功能被标记为extern?我知道这不是一个大问题,因为我很高兴能够根据需要实例化朋友函数(即非extern),但我很想知道是否有办法做到这一点,如果没有,这是疏忽还是故意的事情?
编辑:显而易见的解决方法
我的问题是关于非模板的朋友功能,而不是找到解决方法以避免问题,这是微不足道的。第一个明显的解决方法是:
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>&);
答案 0 :(得分:0)
&#34; extern模板类&#34;是声明一个显式的实例化可用。显式实例化声明的效果不适用于内联函数或模板特化(14.7.2 [temp.explicit]第10段):
除了内联函数和类模板特化之外,显式实例化声明具有抑制它们引用的实体的隐式实例化的效果。
由于类定义中的friend
函数定义必然是inline
函数,因此它将保持inline
函数独立于模板的显式实例化声明(并且,就像你一样正确地指出,它不是模板,也不会遵循模板实例化规则。)