1

I made this code

Declaration:

template <class T>
class Matrix
{
    std::vector< std::vector<T> > mat;
    size_t rows , cols;
public:

    Matrix<T>();
    Matrix<T>(const std::string);
    Matrix(const size_t r, const size_t c, const std::vector<T> v);
    Matrix<T> operator=(const Matrix<T> &other);

    friend std::ostream& operator<<(std::ostream &os , Matrix<T> m);
};

Functions:

template <class T>
std::ostream& operator<<(std::ostream &os , Matrix<T> m){

    for (size_t i = 0; i < m.rows; i++)
    {
        for (size_t j = 0; j < m.cols; j++)
        {
            os << m.mat[i][j] << " ";
        }
        os << std::endl;
    }
    return os;
}

Main :

int main(){
    std::vector<int> v(9);
    v[0] = 1;
    v[1] = 2;
    v[2] = 3;
    v[3] = 4;
    v[4] = 5;
    v[5] = 6;
    v[6] = 7;
    v[7] = 8;
    v[8] = 9;
    Matrix<int> m = Matrix<int>(2, 3, v);
    std::cout << m;
}

I get this error :

Error 1 error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream

&,class Matrix)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@V?$Matrix@H@@@Z) referenced in function _main C:\Users\igor\documents\visual studio 2013\Projects\matrix\matrix\Source.obj matrix

I tried to write it without the friend but got a different error.
What am I doing wrong ?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Igor Gumush
  • 61
  • 2
  • 10
  • Is the definition in a .h file that is `#include`d in `main.cpp`? Posting an [MCVE](http://stackoverflow.com/help/mcve) will be very useful. – R Sahu Jan 08 '15 at 23:06
  • 2
    I don't know if that as any thing to do with your problem (I don't think it does) but you should still have youre function take a `const Matrix&` instead of a `Matrix` – Amxx Jan 08 '15 at 23:07
  • The .h file is included , I tried the other functions and they work fine. – Igor Gumush Jan 08 '15 at 23:09
  • Thanks , changed it but the problem not solved – Igor Gumush Jan 08 '15 at 23:10
  • 1
    @IgorGumush define the templated operator directly in the header file, not in a .cpp file – vsoftco Jan 08 '15 at 23:12
  • 2
    Since this is a template, the *definition* of `operator<<` must be `#include`d with the header. Did you do this? – 5gon12eder Jan 08 '15 at 23:12
  • `template` missing for Matrix declaration? – ryanpattison Jan 08 '15 at 23:13
  • @vsoftco it's all in the header , the main is in .cpp – Igor Gumush Jan 08 '15 at 23:13
  • 1
    http://stackoverflow.com/questions/476272/how-to-properly-overload-the-operator-for-an-ostream – Kenny Ostrom Jan 08 '15 at 23:14
  • Sorry You all right , I copied the function into the class and now it's working – Igor Gumush Jan 08 '15 at 23:16
  • I provided an extensive answer to the different options for operator overloading (and friendship) for templates [here](http://stackoverflow.com/questions/4660123/overloading-friend-operator-for-template-class/4661372). Basically you can either befriend a template, a template specialization or a free function for the operator, but if you want to befriend a non-template function, you need to provide the definition inline. – David Rodríguez - dribeas Jan 09 '15 at 02:51
  • @KennyOstrom: The linked question is about a non-template class. There are additional complications that are related to templates and not present in that linked question. – David Rodríguez - dribeas Jan 09 '15 at 02:52
  • @5gon12eder: The friend function is **not** a template as declared, but a non-templated function. You do want to provide the definition in the header (whether you change the friendship to refer to a template or if you want to provide a non-template friend), but the statement in your comment is incorrect and might *teach* the wrong concepts to other people. – David Rodríguez - dribeas Jan 09 '15 at 02:54
  • @DavidRodríguez-dribeas Good point, and +1 for your linked answer. – 5gon12eder Jan 09 '15 at 03:05

1 Answers1

3

You must implement a template in the header-file, not only declare it there.
Unless, of course, you can explicitly instantiate all the needed specializations.

Anyway, consider defining your friend inline:

template <class T>
class Matrix
{
    //...
    friend std::ostream& operator<<(std::ostream &os , Matrix<T> m) {
        // do things
        return os;
    }
};

You won't be able to call it explicitly unless you also declare it in the containing scope, but ADL will find it, and that's all that you want anyway.

Community
  • 1
  • 1
Deduplicator
  • 44,692
  • 7
  • 66
  • 118