4

我已经开始尝试使用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>&);
4

1 回答 1

0

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

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

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

于 2012-11-02T23:03:27.863 回答