sergih123
sergih123

Reputation: 75

Why do I need to specify the argument list for a class template in a function?

So I have this really simple code that I'm using to get the hang on templates

#include <iostream>

using namespace std;

template <typename T, typename U, typename V>
class Foo{

private:
    T x;
    U y;
    V z;

public:
    Foo(T a, U b, V c){
        this->x = a;
        this->y = b;
        this->z = c;
    }

    friend ostream& operator<<(ostream& os, const Foo &foo);
};

ostream& operator<<(ostream& os, const Foo &foo){

    os << foo->x << ", " << foo->y << ", " << foo->z;
    return os;

}

But it tells me that I need to specify what types (the Foo object that I'm using for overloading the operator) it is using.

Wouldn't that defeat the purpose of templates by having to duplicate code for Foo objects with different Types?

Upvotes: 0

Views: 78

Answers (2)

ShadowRanger
ShadowRanger

Reputation: 155363

You need to make operator<< a template as well, so it can match to an appropriate template instantiation for Foo:

template<typename A, typename B, typename C>
ostream& operator<<(ostream& os, const Foo<A, B, C> &foo){
    os << foo.x << ", " << foo.y << ", " << foo.z; // Changed -> to ., since foo is a reference, not pointer
    return os;
}

Similarly, the friend declaration within the class should be a template, e.g.

template<typename A, typename B, typename C>
friend ostream& operator<<(ostream& os, const Foo<A, B, C>& foo);

A somewhat nicer solution might be to define the friend function entirely within the class, removing the need for explicit templateing:

template <typename T, typename U, typename V>
class Foo{
    // Rest of class here

    // No need for template keyword, extra <>, new typenames, etc.
    friend ostream& operator<<(ostream& os, const Foo<T, U, V>& foo) {
        os << foo.x << ", " << foo.y << ", " << foo.z;
        return os;
    }
};

Upvotes: 5

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

There are at least three mistakes that I can see:

  1. The constructor is trying to access this.x (etc.). But this is a pointer. Furthermore, you should use an initialiser list, not assignment, in the constructor.

  2. Your operator << is attempting to use a non-existent class Foo. You need to convert your function into a function template which uses the class template Foo<T, U, V>. Likewise, your friend function declaration needs to be a function template declaration.

  3. Inside operator <<, foo isn’t a pointer, it’s a value object – use . instead of -> to access members.

Taken together:

#include <iostream>

template <typename T, typename U, typename V>
class Foo{
private:
    T x;
    U y;
    V z;

public:
    Foo(T x, U y, V z) : x(x), y(y), z(y) {}

    template <typename T1, typename U1, typename V1>
    friend std::ostream& operator<<(std::ostream& os, Foo<T1, U1, V1> const& foo);
};

template <typename T, typename U, typename V>
std::ostream& operator<<(std::ostream& os, Foo<T, U, V> const& foo) {
    return os << foo.x << ", " << foo.y << ", " << foo.z;
}

Upvotes: 3

Related Questions