Reputation: 2578
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
Reputation: 48447
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;
}
};
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
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
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