2

I checked the answers to this question: Overloading operator<< for a templated class, but unfortunately nothing is working for me so far. Meaning, the compiler is constantly throwing myriad errors at me.

#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;
}

The error I get:

$ 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

The following version doesn't not work either:

#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;
}

Here's the error I get plus a whole lot more which I'm not going to include here:

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

2 Answers2

3

You need to take ostream in your function by reference. Also, when you declare a friend you need to include the template argument: friend std::ostream& operator<< <T>. Here's your first version modified that works for me:

#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;
}
grigor
  • 1,584
  • 1
  • 13
  • 25
1

The first answer to your referred to question would seem to answer this.

In the first case, you need the friend delcaration to declare a friend template rather than non-template overloaded functions:

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

note the extra <> that designates this as a firend template.

In the second case, you need to prived the template argument to the friend function:

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

note the extra <T>, the type parameter to A

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226