Search code examples
c++arraystemplatesfriend

Why is it not possible to overload insertion operators in c++ for a dynamic array?


I'm new to C++. Just out of curiosity, I'm trying to see what happens when I try to overload the insertion ">>" operator for a class of dynamic array. I think what I'm trying to do is impossible. But could anyone explain what this error means? (error below the code)

#include<iostream>
using namespace std;

template<class Type>
class Array{
    private:
    int length;
    Type* ptrarr;

    public:
        int size() const;
        Type* get_array() const;
        friend istream& operator >> (istream& s, Array<Type>& arr);

};

template<class Type>
int Array<Type>::size() const{
    return length;
}

template<class Type>
Type* Array<Type>::get_array() const{
    return ptrarr;
}

template<class Type>
istream& operator >> (istream& s, Array<Type>& arr){
    cout << "Enter length of array"; cin >> arr.length;
    arr.ptrarr = new Type[arr.length];
    for(int i = 0; i < arr.length; i++){
        cout << "Array[" << i << "] = ";
        cin >> *(arr.ptrarr + i);
    }
    return s;
}


int main(){
    Array<int> intarray;
    cin >> intarray;
    int* ptr = intarray.get_array();
    for(int i =0; i < intarray.size(); i++)
        cout << *(ptr+i);
    return 0;
}

I get the error

in function `main':
dyn_array.cpp:(.text+0x1e): undefined reference to `operator>>(std::istream&, Array<int>&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Solution

  • Your friend declaration refers to a non-template operator>>, which doesn't match the definition of the template one.

    Make the friend declaration refering to the template operator>>, e.g.

    // forward declaration for the class template
    template<class Type>
    class Array;
    // declaration
    template<class Type>
    istream& operator >> (istream& s, Array<Type>& arr);
    

    then

    template<class Type>
    class Array{
        // friend declaration
        friend istream& operator >> <Type> (istream& s, Array<Type>& arr);
        //                          ^^^^^^
        //                  or just <> (make use of template argument deduction)
        ...
    };
    
    // definition
    template<class Type>
    istream& operator >> (istream& s, Array<Type>& arr) {
        ...
    }
    

    Or as Remy Lebeau commented, keep operator >> as non-template, and define it in the class definition.

    template<class Type>
    class Array{
        ...
        friend istream& operator >> (istream& s, Array<Type>& arr) {
            ...
        }
    };