我现在正在学习 C++ 中的模板元编程和表达式模板,所以作为练习,我正在创建一个线性代数库来练习我正在学习的概念。
到目前为止,我的库为所有可以重载的二元运算符提供了一个完整的非成员运算符重载列表,并且具有易于扩展的相当流畅的界面。然而,我遇到的一个问题是矩阵运算通常有多种变化。例如,对于乘法,有一般矩阵乘法、点积、kroenecker 积、hadamard 积、叉积等等。
在 Matlab 中采用的一种巧妙的解决方法是用于 hadamard 乘法(和 .^、./ 等)的 .* 运算符。在这种情况下,Matlab 语言使用 . 运算符作为 * 运算符的修饰符。但是,我不知道 c++ 语言中有任何机制允许像这样修改运算符。这种行为是否有任何干净的解决方法?
以下是我已经想到的一些事情:
- 运算符重载允许额外的模板参数。但是,我不完全确定如何在这种情况下利用这一点。例如,一些可能很好的东西(尽管在实践中,我不确定是否有有效的语法来实现这一点):
template<typename lhs_t, typename rhs_t, typename op_t = Gemm>
auto operator*(lhs_t lhs, rhs_t rhs)
{
...
}
// Operator template specializations ...
int main()
{
Matrix<double, 2, 2> mat1(1.0, 2.0, 3.0, 4.0);
Matrix<double, 2, 2> mat2(1.0, 2.0, 3.0, 4.0);
mat1 * mat2; // Works
mat1 *<Hadamard> mat2; // Error! Syntax????
}
- 使用 SFINAE/Concepts/if constexpr 和特征来修改二进制表达式类型或包装二进制表达式类型。句法:
Hadamard(mat1 * mat2); // Hadamard wraps or modifies binary expression created by operator*
// SFINAE or Concepts used to select the correct routine based on the trait set
- 创建一个免费的二进制函数。可能的语法:
Hadamard<Multiplication>(mat1, mat2);
Hadamard_Multiplication(mat1, mat2);
- 使用成员函数。句法:
mat1.hadamard_multiplication(mat2);
这些似乎都没有像 Matlab 那样优雅的语法:
mat1 .* mat2;
是否有任何技术可以接近我可以考虑的运算符修饰符语法?或者任何使使用语法不那么冗长的一般技术?如果没有,是否有任何想法可以在未来的 C++ 版本中包含一些在这里可能有用的东西?