外部模板类和非模板友元函数

时间:2012-10-13 23:27:06

标签: c++ templates c++11 extern

我开始使用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>&);

1 个答案:

答案 0 :(得分:0)

&#34; extern模板类&#34;是声明一个显式的实例化可用。显式实例化声明的效果不适用于内联函数或模板特化(14.7.2 [temp.explicit]第10段):

  

除了内联函数和类模板特化之外,显式实例化声明具有抑制它们引用的实体的隐式实例化的效果。

由于类定义中的friend函数定义必然是inline函数,因此它将保持inline函数独立于模板的显式实例化声明(并且,就像你一样正确地指出,它不是模板,也不会遵循模板实例化规则。)