- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写 Matrix 类层次结构,但在重载用于矩阵与矩阵相乘的乘法运算符以及通过标量缩放矩阵时遇到了麻烦。我使用 std::enable_if_t 来根据要相乘的类型是否为矩阵来消除应该调用哪个运算符的歧义。判断一个变量是否为矩阵是通过检查它是否继承自一个空的基类matrix_tag来判断的。下面是代码的一个相当小的可重现示例:
#include <type_traits>
#include <vector>
// Forward declaration
template <typename T, size_t N, size_t M> class Matrix;
// Empty base class for all matrices, to enable checking whether a type is a
// matrix
struct matrix_tag {};
template <typename MatrixType> struct is_matrix {
static constexpr bool value =
std::is_base_of<matrix_tag, MatrixType>::value;
};
template <typename MatrixType>
constexpr bool Is_matrix = is_matrix<MatrixType>::value;
// Helper type function: The result of multiplying two generic types
template <typename T1, typename T2> struct product_type {
using type = decltype(std::declval<T1>() * std::declval<T2>());
};
// Convenience wrapper
template <typename T1, typename T2>
using Product_type = typename product_type<T1, T2>::type;
// Compile time dispatch for the result of matrix multiplications
template <typename Matrix1, typename Matrix2> struct matrix_product_type {
static constexpr size_t N = Matrix1::number_of_rows;
static constexpr size_t M = Matrix2::number_of_cols;
static_assert(Matrix1::number_of_cols == Matrix2::number_of_rows);
using element_type = Product_type<typename Matrix1::element_type,
typename Matrix2::element_type>;
using type = Matrix<element_type, N, M>;
};
// Convenience wrapper
template <typename Matrix1, typename Matrix2>
using Matrix_product_type =
typename matrix_product_type<Matrix1, Matrix2>::type;
// Compile time dispatch for Matrix scaling
template <typename MatrixType, typename T> struct scaled_matrix_type {
static constexpr size_t N = MatrixType::number_of_rows;
static constexpr size_t M = MatrixType::number_of_cols;
using element_type = Product_type<typename MatrixType::element_type, T>;
using type = Matrix<element_type, N, M>;
};
// Convenience wrapper
template <typename MatrixType, typename T>
using Scaled_matrix_type = typename scaled_matrix_type<MatrixType, T>::type;
// Class definition
template <typename T, size_t N, size_t M> class Matrix : public matrix_tag {
public:
// Types
using element_type = T;
// Traits
static constexpr size_t number_of_rows = N;
static constexpr size_t number_of_cols = M;
// Default constructor
Matrix() : elements_(N * M, 0) {}
// Public access functions
virtual const T &operator()(size_t row, size_t col) const {
return elements_[row * number_of_cols + col];
}
virtual T &operator()(size_t row, size_t col) {
return const_cast<T &>(
(*static_cast<const Matrix *>(this))(row, col));
}
private:
// Element storage
std::vector<T> elements_;
};
// Scaling
// Returns a new matrix with element_type reflecting the result of
// elementwise multiplication
template <typename MatrixType, typename T>
std::enable_if_t<(Is_matrix<MatrixType> && !Is_matrix<T>),
Scaled_matrix_type<MatrixType, T>>
operator*(const MatrixType &A, const T &x) {
typename scaled_matrix_type<MatrixType, T>::type B = A;
for (size_t i = 0; i != B.number_of_rows; ++i) {
for (size_t j = 0; j != B.number_of_rows; ++j) {
B(i, j) *= x;
}
}
return B;
}
template <typename T, typename MatrixType>
std::enable_if_t<(!Is_matrix<T> && Is_matrix<MatrixType>),
Scaled_matrix_type<MatrixType, T>>
operator*(const T &x, const MatrixType &A) {
return A * x;
}
// Matrix multiplication
template <typename Matrix1, typename Matrix2>
std::enable_if_t<(Is_matrix<Matrix1> && Is_matrix<Matrix2>),
Matrix_product_type<Matrix1, Matrix2>>
operator*(const Matrix1 &A, const Matrix2 &B) {
typename matrix_product_type<Matrix1, Matrix2>::type C;
for (size_t i = 0; i != A.number_of_rows; ++i) {
for (size_t j = 0; j != B.number_of_cols; ++j) {
for (size_t k = 0; k != A.number_of_cols; ++k) {
C(i, j) += A(i, k) * B(k, j);
}
}
}
return C;
}
int main() {
Matrix<double, 4, 3> A{};
Matrix<float, 3, 2> B{};
auto C = A * B;
}
Clang 给了我一堆与此类似的错误:
error: type 'int' cannot be used prior to '::' because it has no members static_assert(Matrix1::number_of_cols == Matrix2::number_of_rows);
在我看来,这应该是替换失败而不是编译错误。给了什么?
最佳答案
从这段代码来看:
template <typename Matrix1, typename Matrix2>
std::enable_if_t<(Is_matrix<Matrix1> && Is_matrix<Matrix2>),
Matrix_product_type<Matrix1, Matrix2>>
operator*(const Matrix1 &A, const Matrix2 &B) {...}
如果第一个模板参数为假,您似乎希望完全丢弃第二个模板参数(无需任何验证)。
但这里发生的是,两个模板参数都先被验证,然后如果条件结果为假,则第二个参数被丢弃。
自从使用 Matrix_product_type
使用非矩阵模板参数是一个硬错误(而不是 SFINAE 可检测的错误),你在 enable_if_t
之前得到一个硬错误有机会上场。
最直接的解决方案是为 enable_if_t
创建第二个模板参数无论条件是否为真都有效。
一种可能的方法是:
template <typename Matrix1, typename Matrix2>
typename std::enable_if_t<(Is_matrix<Matrix1> && Is_matrix<Matrix2>),
matrix_product_type<Matrix1, Matrix2>>::type
operator*(const Matrix1 &A, const Matrix2 &B)
请注意,我替换了 Matrix_product_type
(类型别名)与 matrix_product_type
(struct
)。
这边matrix_product_type<>::type
除非条件为真,否则不会被访问。
您可能需要对 operator*
的其他重载进行类似的更改
关于c++ - 为什么重载运算符时会出现编译错误而不是替换失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54847294/
Or 运算符 对两个表达式进行逻辑“或”运算。 result = expression1 Or expression2 参数 result 任意数值变量。 expression1 任意
Not 运算符 对表达式执行逻辑非运算。 result = Not expression 参数 result 任意数值变量。 expression 任意表达式。 说明 下表显示如何
Is 运算符 比较两个对象引用变量。 result = object1 Is object2 参数 result 任意数值变量。 object1 任意对象名。 object2 任意
\ 运算符 两个数相除并返回以整数形式表示的结果。 result = number1\number2 参数 result 任意数值变量。 number1 任意数值表达式。 numbe
And 运算符 对两个表达式进行逻辑“与”运算。 result = expression1 And expression2 参数 result 任意数值变量。 expression1
运算符(+) 计算两个数之和。 result = expression1 + expression2 参数 result 任意数值变量。 expression1 任意表达式。 exp
我对此感到困惑snippet : var n1 = 5-"4"; var n2 = 5+"4"; alert(n1); alert(n2); 我知道 n1 是 1。那是因为减号运算符会将字符串“4”转
我想我会得到 12,而不是 7。 w++,那么w就是4,也就是100,而w++, w 将是 8,1000;所以 w++|z++ 将是 100|1000 = 1100 将是 12。 我怎么了? int
Xor 运算符 对两个表达式进行逻辑“异或”运算。 result = expression1 Xor expression2 参数 result 任意数值变量。 expression1
Mod 运算符 两个数值相除并返回其余数。 result = number1 Mod number2 参数 result 任意数值变量。 number1 任意数值表达式。 numbe
Imp 运算符 对两个表达式进行逻辑蕴涵运算。 result = expression1 Imp expression2 参数 result 任意数值变量。 expression1 任
Eqv 运算符 执行两个表达式的逻辑等价运算。 result = expression1 Eqv expression2 参数 result 任意数值变量。 expression1 任
我有一个运算符重载的简单数学 vector 类。我想为我的运算符(operator)获取一些计时结果。我可以通过计时以下代码轻松计时我的 +=、-=、*= 和/=: Vector sum; for(s
我是用户定义比较运算符的新手。我正在读一本书,其中提到了以下示例: struct P { int x, y; bool operator、运算符<等),我们
在 SQL 的维基百科页面上,有一些关于 SQL 中 bool 逻辑的真值表。 [1] 维基百科页面似乎来源于 SQL:2003 标准。 等号运算符 (=) 的真值表与 SQL:2003 草案中的 I
我遇到了一个奇怪的 C++ 运算符。 http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f
我正在阅读关于 SO 和 answers 中的一个问题,它被提到为: If no unambiguous matching deallocation function can be found, pr
我偶然发现了这个解决方案,但我无法理解其中到底发生了什么。谁能解释一下! 据我了解,它试图通过计算一半的单元格然后将其加倍来计算 a*b 网格中的单元格数量。但是我无法理解递归调用。 请不要建议其他解
Go的基本类型 布尔类型bool 长度:1字节 取值:布尔类型的取值只能是true或者false,不能用数字来表示 整型 通用整型 int / uint(有符号 / 无符号,下面也类似) 长度:根据运
在本教程中,您将学习JavaScript中可用的不同运算符,以及在示例的帮助下如何使用它们。 什么是运算符? 在JavaScript中,运算符是一种特殊符号,用于对运算数(值和变量)执行操作。例如,
我是一名优秀的程序员,十分优秀!