Surajeet Bharati
Surajeet Bharati

Reputation: 1433

Template Class with stream operator overloading

I am trying to get a better understanding on some advanced staffs of C++. I am trying to understand stream operator overloading , friend function and template now. I am trying to learn all these things in a single code segment.

So, I am trying to implement a template class which will just contain an array, which I want to populate with stream operator. So,I came up with this.

#include <iostream>
using namespace std;

template<class T, int L>
class TestClass
{
    private:
        T data[L];
    public:
        friend void operator>>(const istream&, const TestClass<T,L>&);
};

template<class T, int L>
void operator>>(const istream& in, const TestClass<T,L>& q)
{
    for(int i = 0; i < L; i++)
    {
        in >> q.data[i];
    }
}

int main() {
    TestClass<float, 3> Q;
    cin >> Q;

    return 0;
}

This is pretty easy code segment. But, I am getting following error on compilation

undefined reference to `operator>>(std::istream const&, TestClass<float, 3> const&)'

with the following warning

warning: friend declaration 'void operator>>(const istream&, const TestClass<T, L>&)' declares a non-template function [-Wnon-template-friend]|

I know, I am doing some rookie mistake, as I am pretty new to this things. It will be great if someone helps to run this successfully.

Upvotes: 2

Views: 1513

Answers (1)

AndyG
AndyG

Reputation: 41220

The issue is two-fold:

  1. Your friend function should also be a template
  2. You are passing the istream and TestClass as const. Remove that

Here is updated code:

template<class T, int L>
class TestClass
{
    private:
        T data[L];
    public:
        template<class U, int M>
        friend void operator>>(istream&, TestClass<U,M>&);
};

template<class T, int L>
void operator>>(istream& in, TestClass<T,L>& q)
{
    for(int i = 0; i < L; i++)
    {
        in >> q.data[i];
    }
}

Demo


Edit: Other equally valid approaches

Slightly different syntax to declare the friend and everything will work Demo:

template<class T, int L>
class TestClass
{
    private:
        T data[L];
    public:
        friend void operator>> <>(istream&, TestClass&);
};

(Thanks @chris). This format (with the <>) differs from the above example in that the above is technically declaring all instantiations of operator>> to be a friend whereas this one only has a one-to-one relationship.

Alternatively you could include the definition along with the friend declaration Demo:

template<class T, int L>
class TestClass
{
    private:
        T data[L];
    public:
        friend void operator>>(istream& in, TestClass& q){
            for(int i = 0; i < L; i++)
            {
                in >> q.data[i];
            }       
        }
};

Upvotes: 3

Related Questions