运算符&lt;(&ostream&amp;,const BigUnsigned <i>&amp;)必须只接受一个参数

时间:2016-01-21 15:44:45

标签: c++ templates c++11 operator-overloading

我尝试将模板化类的模板化成员函数的声明和定义分开,但最终出现以下错误和警告。

template <typename I>
class BigUnsigned{
    const size_t cell_size=sizeof(I);
    std::vector<I> _integers;
public:
    BigUnsigned();
    BigUnsigned(I);
    friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu);
};

std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
    for (auto integer : bu._integers){
        out<<integer<<std::endl;
    }
    return out;
}
  

../ hw06 / bigunsigned.h:13:77:警告:朋友声明   “的std :: ostream的和放;运算符&lt;&lt;(std :: ostream&amp;,const BigUnsigned&amp;)'   声明一个非模板函数[-Wnon-template-friend]        朋友std :: ostream&amp; operator&lt;&lt;(std :: ostream&amp; out,const BigUnsigned&amp; bu);                                                                                ^ ../hw06/bigunsigned.h:13:77:注意:(如果这不是你的话   预期,确保已声明功能模板   并添加&lt;&gt;在这里的函数名称之后)../hw06/bigunsigned.h:16:51:   错误:无法使用模板名称'BigUnsigned'而没有参数   list std :: ostream&amp;运算符&lt;&lt;(std :: ostream&amp; out,const BigUnsigned&amp;   BU){                                                      ^ ../hw06/bigunsigned.h:在函数'std :: ostream&amp;   operator&lt;&lt;(std :: ostream&amp;,const int&amp;)':../ hw06 / bigunsigned.h:17:28:   错误:请求'bu'中的成员'_integers',这是非类的   输入'const int'        for(auto integer:bu._integers){                               ^

当我加入这样的声明和定义时,一切都很好。

template <typename I>
class BigUnsigned{
    const size_t cell_size=sizeof(I);
    std::vector<I> _integers;
public:
    BigUnsigned();
    BigUnsigned(I);
    friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
        for (auto integer : bu._integers){
            out<<integer<<std::endl;
        }
        return out;
    }
};

目的是将成员变量_integers打印到cout。可能是什么问题?

P.S。:使用this question我使这个函数免费,但没有帮助。

3 个答案:

答案 0 :(得分:7)

BigUnsigned是模板类型,所以

std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu)

无效,因为没有BigUnsigned。您需要将朋友功能设为模板,以便您可以使用不同类型的BigUnsigned<some_type>

template <typename I>
class BigUnsigned{
    const size_t cell_size=sizeof(I);
    std::vector<I> _integers;
public:
    BigUnsigned();
    BigUnsigned(I);
    template<typename T>
    friend std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu);
};

template<typename T>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu){
    for (auto integer : bu._integers){
        out<<integer<<std::endl;
    }
    return out;
}

第二个例子的作用是因为它在类中声明它使用类使用的模板类型。

答案 1 :(得分:4)

the answer by NathanOliver的改进。

使用另一个答案,函数模板的所有实例化都是类模板的所有实例的friend

operator<< <int>friend BigUnsigned<int>以及BigUnsigned<double>

operator<< <double>friend BigUnsigned<double>以及BigUnsigned<FooBar>

您可以稍微更改声明,以便

operator<< <int>friend BigUnsigned<int>但不是BigUnsigned<double>

operator<< <double>friend BigUnsigned<double>但不是BigUnsigned<FooBar>

// Forward declaration of the class template.
template <typename I> class BigUnsigned;

// Forward declaration of the function template
template <typename I>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<I>& bu);

// Change the friend-ship declaration in the class template.
template <typename I>
class BigUnsigned{
    const size_t cell_size=sizeof(I);
    std::vector<I> _integers;
public:
    BigUnsigned();
    BigUnsigned(I);

    // Grant friend-ship only to a specific instantiation of the
    // function template.
    friend std::ostream& operator<< <I>(std::ostream& out, const BigUnsigned<I>& bu);
};

答案 2 :(得分:1)

添加第三个可提高可读性的变体是在类中定义友元函数:

#include <iostream>

template <typename T>
class Foo {
    int test = 42;

    // Note: 'Foo' inside the class body is basically a shortcut for 'Foo<T>'
    // Below line is identical to: friend std::ostream& operator<< (std::ostream &os, Foo<T> const &foo)
    friend std::ostream& operator<< (std::ostream &os, Foo const &foo) {
        return os << foo.test;
    }
};


int main () {
    Foo<int> foo;
    std::cout << foo << '\n';
}