Я хотел спроектировать матрицу и хотел, чтобы ее нельзя было плохо инициализировать. Рассмотрим, например, это:
template <typename T, unsigned int R, unsigned int C>
class matrix {
array<T,R*C> _data;
//... Constructors, etc. ...
};
Теперь я хотел бы иметь дизайн, в котором возможно или даже нет следующее:
auto mat1 = matrix<int,2,2>{1, 2, 3, 4};
auto mat2 = matrix<int,2,2>{1, 2, 3, 4, 5}; // Error! Hopefully at compile time
auto mat3 = matrix{1,2,3,4}; // matrix<int,2,2>
Есть ли элегантный способ выразить это? С конструкторами и initializer_list? Можно ли проверить размер предоставленных аргументов?
Вместо array<T,R*C>
удобнее иметь array<array<T, R>, C>
.
Вы можете добавить конструктор, принимающий произвольное количество аргументов + руководство по выводу для расчета размеров:
template <class T, std::size_t R, std::size_t C>
struct matrix {
// take anything and forward it:
template <class... Args>
matrix(Args&&... args) : _data{std::forward<Args>(args)...} {
// assert that the sizes are correct:
static_assert(sizeof...(Args) == R * C, "invalid init");
}
std::array<T, R * C> _data;
};
// integer square root
template<std::size_t T, std::size_t N = 0>
constexpr std::size_t isqrt() {
if constexpr ((N+1) * (N+1) <= T) return isqrt<T, N + 1>();
return N;
}
// Deduction guide:
template <class T, class... Args>
matrix(T&&, Args&&...) ->
matrix<T, isqrt<sizeof...(Args) + 1>(), isqrt<sizeof...(Args) + 1>()>;
Не ответ на ваш вопрос, но вы можете взглянуть на собственные библиотеки: eigen.tuxfamily.org/index.php?title=Main_Page