TeaOverflow
TeaOverflow

Reputation: 2578

passing a templated class with constants as an argument

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?

Upvotes: 0

Views: 932

Answers (3)

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48447

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;
}

Upvotes: 1

Abhijit
Abhijit

Reputation: 63727

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;
     }
};

Upvotes: 2

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42899

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;
}

Upvotes: 1

Related Questions