0

My template class looks like this:

template<unsigned WIDTH, unsigned HEIGTH, typename T = int> class matrix { ... }

So plain and simple, the template arguments determine this size of the matrix. The size is logically constant, so I implemented it to be consant. But when I try to write a function that accepts my matrix, I run into the following problem:

std::ostream& operator<<(std::ostream &os, const matrix &m){ ...}

Writen like so, the compiler rightfully objects the lack of template arguments... But

std::ostream& operator<<(std::ostream &os, const matrix<unsigned, unsigned> &m){ ...}

triggers this error: error: expected a constant of type 'unsigned int', got 'unsigned> int'

Which is also kind of true, since matrix expects constants, not types.

How to deal with this? I'm sure I'm not the frst to encounter this problem, what's the most "canonical" way to approach this problem of passing constant-parametrized templates?

TeaOverflow
  • 2,468
  • 3
  • 28
  • 40

3 Answers3

2

Declare your operator<<(ostream&) overload for your template class matrix as a template which should be the obvious solution here

template<unsigned WIDTH, unsigned HEIGTH, typename T = int> 
class matrix 
{ 
public:
    T arr[WIDTH][HEIGTH];
};
template<unsigned WIDTH, unsigned HEIGTH, typename T>
std::ostream& operator<<(std::ostream &os, const matrix<WIDTH, HEIGTH,T> &m)
{ 
    // formatting inserter of m  onto os
    return os;
}

int main()
{
    matrix<10, 10> m;
    std::cout << m << std::endl;
}

But generally speaking, if your operator<<(ostream&) needs access to your private data (which generally would), you would end up declaring it as friend. If you do not want to repeat the remplate parameters, place the operator<<(ostream&) non-member friend in the scope of your matrix class

template<unsigned WIDTH, unsigned HEIGTH, typename T = int> 
class matrix 
{ 
     T arr[WIDTH][HEIGTH];
     friend std::ostream& operator<<(std::ostream &os, const matrix &m)
     { 
         // formatting inserter of m  onto os
         return os;
     }
};
Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • At least you're pretty consistent in spelling HEIGTH wrong :p (up voted) – Carlo Wood Sep 12 '14 at 20:51
  • @CarloWood: Actually, I copied it from OP and never noticed that its misspelled. In any case I will leave it to be in sync with OPs question :-) – Abhijit Sep 12 '14 at 20:55
1

Option #1

Declare the operator<< as a friend function in the scope of the matrix class:

template<unsigned WIDTH, unsigned HEIGTH, typename T = int>
class matrix
{
    friend std::ostream& operator<<(std::ostream &os, const matrix& m)
    //                                                      ^^^^^^ plain name
    {
        return os;
    }
};

Option #2

Make operator<< a function template as well:

template<unsigned WIDTH, unsigned HEIGHT, typename T>
std::ostream& operator<<(std::ostream &os, const matrix<WIDTH, HEIGHT, T>& m)
//                                                      ^^^^^  ^^^^^^  ^
{
    return os;
}
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
1

Overloaded operator<< needs to be template as well:

template<unsigned WIDTH, unsigned HEIGHT, typename T>
std::ostream& operator<<(std::ostream &os, const matrix<WIDTH, HEIGHT, T> &m){
  // ...
  return os;
}
101010
  • 41,839
  • 11
  • 94
  • 168