передача шаблонного класса с константами в качестве аргумента

Мой шаблонный класс выглядит так:

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

Простые и понятные аргументы шаблона определяют размер матрицы. Размер логически постоянен, поэтому я реализовал его так, чтобы он был согласованным. Но когда я пытаюсь написать функцию, которая принимает мой matrixЯ сталкиваюсь со следующей проблемой:

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

Написанный так, компилятор справедливо возражает против отсутствия аргументов шаблона … Но

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

вызывает эту ошибку: error: expected a constant of type 'unsigned int', got 'unsigned> int'

Что также отчасти верно, так как matrix ожидает константы, а не типы.

Как с этим бороться? Я уверен, что я не первый, кто сталкивается с этой проблемой, каков наиболее «канонический» способ решения этой проблемы передачи константно-параметризованных шаблонов?

0

Решение

Опция 1

Объявить operator<< как друг функция в рамках matrix учебный класс:

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

Вариант № 2

Делать operator<< также шаблон функции:

template<unsigned WIDTH, unsigned HEIGHT, typename T>
std::ostream& operator<<(std::ostream &os, const matrix<WIDTH, HEIGHT, T>& m)
//                                                      ^^^^^  ^^^^^^  ^
{
return os;
}
1

Другие решения

Объявите свой operator<<(ostream&) перегрузка для вашего шаблона класса matrix в качестве шаблона, который должен быть очевидным решением здесь

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

Но, вообще говоря, если ваш operator<<(ostream&) нужен доступ к вашим личным данным (что обычно бывает), вы в конечном итоге объявите их как друзей. Если вы не хотите повторять параметры remplate, поместите operator<<(ostream&) не являющийся членом в рамках вашей матрицы класса

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

перегруженный operator<< также должен быть шаблон:

template<unsigned WIDTH, unsigned HEIGHT, typename T>
std::ostream& operator<<(std::ostream &os, const matrix<WIDTH, HEIGHT, T> &m){
// ...
return os;
}
1