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

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

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 ожидает константы, а не типы.

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

3 ответа

Решение

Опция 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;
}

Объявите свой 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;
     }
};

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

template<unsigned WIDTH, unsigned HEIGHT, typename T>
std::ostream& operator<<(std::ostream &os, const matrix<WIDTH, HEIGHT, T> &m){
  // ...
  return os;
}
Другие вопросы по тегам