如何正确地重载用户定义的命名空间的模板类的插入操作符?

时间:2016-08-18 21:33:57

标签: c++

我检查了这个问题的答案:Overloading operator<< for a templated class,但不幸的是到目前为止我没有任何工作。意思是,编译器不断向我抛出无数错误。

#include <iostream>


namespace usr {
    // Forward declarations
    template <typename T> class A;
    template <typename T>
    std::ostream& operator<<(std::ostream& os, const usr::A<T>&);

    template <typename T>
    class A {
        public:
            friend std::ostream& operator<<(std::ostream& os,
                                            const usr::A<T>& a);
    };

    template <typename T>
    std::ostream& operator<<(std::ostream& os, const usr::A<T>& a) {
        os << "test";
        return os;
    }
}

int main() {
    usr::A<int> a;
    std::cout << a << std::endl;


    return 0;
}

我得到的错误:

$ g++ -std=c++11 test.cpp && ./a.out 
test.cpp:15:67: warning: friend declaration ‘std::ostream& usr::operator<<(std::ostream&, const usr::A<T>&)’ declares a non-template function [-Wnon-template-friend]
                                                 const usr::A<T>& a);
                                                                   ^
test.cpp:15:67: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 
/tmp/ccklebu2.o: In function `main':
test.cpp:(.text+0x24): undefined reference to `usr::operator<<(std::ostream&, usr::A<int> const&)'
collect2: error: ld returned 1 exit status

以下版本也不起作用:

#include <iostream>

namespace usr {
    template <typename T>
    class A {
        public:
            friend std::ostream& operator<<(std::ostream& os, const usr::A& a) {
                os << "test";
                return os;
            }
    };
}

int main() {
    usr::A<int> a;
    std::cout << a << std::endl;


    return 0;
}

这是我得到的错误以及我将不会包含的更多内容:

test2.cpp:8:55: error: invalid use of template-name ‘usr::A’ without an argument list
                                                 const usr::A& a) {

2 个答案:

答案 0 :(得分:3)

您需要通过引用在函数中使用ostream。此外,当您声明朋友时,您需要包含模板参数:friend std::ostream& operator<< <T>。这是您修改的第一个版本,对我有用:

#include <iostream>

namespace usr {
    // Forward declarations
    template <typename T> class A;

    template <typename T>
    std::ostream& operator<<(std::ostream& os, const usr::A<T>&);

    // Class
    template <typename T>
    class A {
        public:
            friend std::ostream& operator<< <T>(std::ostream& os, const usr::A<T>& a);
    };

    // Friend function
    template <typename T>
    std::ostream& operator<<(std::ostream& os, const usr::A<T>& a) {
        os << "test";
        return os;
    }
}

int main() {
    usr::A<int> a;
    std::cout << a << std::endl;


    return 0;
}

答案 1 :(得分:1)

您提到的问题的第一个答案似乎就是回答这个问题。

在第一种情况下,您需要使用朋友级别来声明朋友模板而不是非模板重载函数:

 friend std::ostream& operator<< <>(std::ostream &os, const usr::A<T>& a);

请注意额外的<>,将其指定为一个firend模板。

在第二种情况下,您需要将模板参数赋予友元函数:

friend std::ostream& operator<<(std::ostream &os, const usr::A<T>& a) {

请注意额外的<T>A

的类型参数