【发布时间】:2023-02-11 03:56:44
【问题描述】:
这个 sn-p 是 C++20 代码库中的一个小例子。将矩阵相互相乘是一项免费功能。 Matrix 本身是在 ROWS 和 COLUMNS 上模板化的,就像 std::array 一样,这使得在函数接口中使用有点痛苦。
完整的类型名称变成了Matrix<ROWS, COLUMNS>,这本身很好,但是当重复三次(对于返回值和两个参数)时,它确实会损害函数接口的可读性。
现代 C++ 中有哪些语法或策略可以减少重复类型名称的干扰?
template <uint8_t ROWS, uint8_t COLUMNS>
Matrix<ROWS, COLUMNS> operator*(const Matrix<ROWS, COLUMNS>& lhs, const Matrix<ROWS, COLUMNS>& rhs) noexcept {
Matrix<ROWS, COLUMNS> result;
for (uint8_t row = 0; row < ROWS; ++row) {
for (uint8_t col = 0; col < COLUMNS; ++col) {
for (uint8_t i = 0; i < COLUMNS; ++i) {
result(row, col) += lhs(row, i) * rhs(i, col);
}
}
}
return result;
}
要求:
- 所有矩阵(参数和返回值)必须具有相同的维度
- 矩阵知道自己的大小(
.columns()、.rows()),因此我们不需要在这些循环中使用模板参数。 - Matrix 还提供了一个
::size_type,所以理想的解决方案是让我们使用它(干干净净) 而不是在循环中硬编码uint8_t。
【问题讨论】:
-
auto operator*(const Matrix<ROWS, COLUMNS>& lhs, decltype(lhs) rhs) -
定义一个
matrix概念,然后是类似template <matrix LHS, std::same_as<LHS> RHS> LHS operator*(const LHS& lhs, const RHS& rhs)的概念。 -
^That,并让维度成为静态成员。然后你写
for(LHS::size_type row = 0; row < lhs.rows; row++) ...。此外,使用uint8_t作为索引听起来像是等待发生的溢出。 -
你可以让它成为朋友并在类模板中定义它
-
最简单的,如果你在类本身内部实现它,因为在这种情况下你可以简单地省略模板参数。您甚至不需要为此使用特定的 C++ 标准。
template <uint8_t ROWS, uint8_t COLUMNS> class Matrix{... friend Matrix operator*(Matrix const& lhs, Matrix const& rhs) { ... } };,请参阅此处的 (2):en.cppreference.com/w/cpp/language/friend
标签: c++ api templates coding-style