英文:
How to design a matrix in C++
问题
以下是翻译的代码部分:
我想设计一个矩阵,并希望不能初始化它不当。例如,考虑以下情况:
template <typename T, unsigned int R, unsigned int C>
class matrix {
std::array<T, R*C> _data;
//... 构造函数等 ...
};
现在,我想要一个设计,其中以下操作是可能的,甚至不可能的:
auto mat1 = matrix<int, 2, 2>{1, 2, 3, 4};
auto mat2 = matrix<int, 2, 2>{1, 2, 3, 4, 5}; // 错误!希望在编译时发生错误
auto mat3 = matrix{1, 2, 3, 4}; // matrix<int, 2, 2>;
是否有一种优雅的方式来表达这一点?使用构造函数和初始化列表吗?是否可以检查所提供的参数的大小?
英文:
I wanted to design a matrix and wanted that it is not possible to initialize it bad. Consider for example this:
template <typename T, unsigned int R, unsigned int C>
class matrix {
array<T,R*C> _data;
//... Constructors, etc. ...
};
Now I would like to have a design where the following is possible or even not:
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>
Is there a elegant way to express that? With Constructors and initializer_list? Is it possible to check the size of provided arguments?
答案1
得分: 3
你可以添加一个接受任意数量参数的构造函数 + 一个推导指南来计算大小:
template<class T, std::size_t R, std::size_t C>
struct matrix {
// 接受任意类型并进行转发:
template<class... Args>
matrix(Args&&... args) : _data{std::forward<Args>(args)...} {
// 断言大小是否正确:
static_assert(sizeof...(Args) == R * C, "初始化无效");
}
std::array<T, R * C> _data;
};
// 整数平方根
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;
}
// 推导指南:
template<class T, class... Args>
matrix(T&&, Args&&...) ->
matrix<T, isqrt<sizeof...(Args) + 1>(), isqrt<sizeof...(Args) + 1>()>;
英文:
You could add a constructor taking an arbitrary amount of arguments + a deduction guide to calculate the sizes:
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>()>;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论