类模板友化函数模板

Class template befriending function template

本文关键字:函数模板      更新时间:2023-10-16

当我尝试从以下代码创建可执行文件时,我得到一个链接器错误。我得到的印象是,我需要在周围放置一些"typename"或做一些向前声明;我试过几种组合,但都不起作用。

template<typename T>
class enabled
{
  private:
    T type_;
    friend const T& typeof(const enabled<T>& obj); // Offending line
};
template<typename T>
const T& typeof(const enabled<T>& obj) {
    return obj.type_;
}

int main()
{
    enabled<std::string> en;
    std::cout << typeof(en);
    std::cin.clear(), std::cin.get();
    return 0;
}

1>主要。object: error LNK2001:无法解析的外部符号"class std::string consts&__cdecl typeof(类启用<类std::string> const&)"

通过前向声明并指定函数是模板化的

template<typename T> class enabled;
template<typename T>
const T& typeof(const enabled<T>& obj) {
    return obj.type_;
}
template<typename T>
class enabled
{
  private:
    T type_;
    friend const T& typeof<>(const enabled<T>& obj);
};

问题是,作为类友元的函数不是函数模板,而您实际定义的函数是函数模板。

你所需要做的就是将友元设置为函数模板,如下所示:

template<typename T>
class enabled
{
  private:
    T type_;
    template<typename U> //<-------------------------------note this
    friend const U& typeof_(const enabled<U>& obj);  //use U 
};

现在编译得很好:http://www.ideone.com/VJnck

但是它使得typeof_<U>的所有实例化都是enabled<T>的实例化的朋友,这意味着对于T的所有可能值,typeof_<int>都是enabled<T>的朋友,反之亦然。

因此,一个更好的解决方案是使函数非模板在类中定义为:
template<typename T>
class enabled
{
  private:
    T type_;
    friend const T& typeof_(const enabled<T>& obj)
    {
        return obj.type_;
    }
};

Demo: http://www.ideone.com/Rd7Yk

请注意,我将typeof替换为typeof_,因为GCC有一个名为typeof的扩展,因此它在ideone上给出错误(因为我不能关闭扩展)。