5

我在这里阅读了 litb 对一个问题的回答,他详细说明了如何创建类模板的专用友元函数

我试图创建一个符合他建议的示例(最后的代码):

// use '<>' to specialize the function template with the class template's type
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f)

它会导致编译器错误

error: defining explicit specialization ‘operator<< <>’ in friend declaration

在特化中显式声明模板参数也不起作用:

friend std::ostream& operator<< <T>(std::ostream& os, const foo<T>& f) // same error

另一方面,从使用特化改为使用友元函数模板确实有效:

template<typename U>
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works

所以我的问题是:

  • 是什么导致了第一个错误?
  • 我怎样才能明确地专门ostream operator化周围的类模板专业化?

下面的示例代码:

#include <iostream>

// fwd declarations
template<typename T> struct foo;
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&);

template<typename T>
struct foo
{
    foo(T val)
        : _val(val)
    {}

    friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f) // error line
    //template<typename U>
    //friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
    {
        return os << "val=" << f._val;
    }

    T _val;
};


int main()
{
    foo<std::string> f("hello world");
    std::cout << f << std::endl;
    exit(0);
}
4

2 回答 2

3

在 litb 的示例中,他只是将专业化声明为班级中的朋友。他没有定义专业化,这是您的代码正在做的事情。不允许在类声明(或任何非命名空间范围)中定义特化。

你需要的是这样的:

template <class T>
class foo;

template<class T>
std::ostream& operator<<(std::ostream& os, const foo<T>& f)
{
    return os << "val=" << f._val;
}

template<typename T> 
struct foo
{
    // ...
private:
    friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f);
    T _val;
};
于 2012-11-19T23:26:46.910 回答
2

您有 2 个选择:

删除 fwd 声明并定义类中的所有内容。

例子

template <typename U>
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
{
    return os << "val=" << f._val;
}

在类之外定义友元函数。

例子

template<typename T> struct foo;
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&);

template<typename T>
struct foo
{
    foo(T val)
        : _val(val)
    {}

    friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f);

    T _val;
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const foo<T>& f)
{
       return os << "val=" << f._val;
}
于 2012-11-19T23:24:32.327 回答