我已经开始尝试使用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 上测试)。
有什么方法可以让朋友功能被标记为外部?我知道这不是一个大问题,因为我可以愉快地接受根据需要实例化的朋友函数(即非外部函数),但我很想知道是否有办法做到这一点,如果没有的话,是疏忽还是故意的?
编辑:明显的解决方法
我的问题特别是关于非模板友元函数,而不是寻找解决方法来避免这个问题,这是微不足道的。第一个明显的解决方法是:
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>&);