I am learning about template meta programming and expression templates in C++ right now, so as an exercise, I am creating a linear algebra library to practice the concepts I am learning.
So far, my library has a complete list of non-member operator overloads for all of the binary operators that can be overloaded, and has a fairly-slick interface that's easily expandable. One problem I've run into, however, is that matrix operations often have multiple variations. For example, for multiplication, there is the general matrix multiplication, the dot product, the kroenecker product, the hadamard product, the cross product, and more.
One slick way around this that is employed in Matlab is the .* operator used for hadamard multiplication (and .^, ./, etc). In this case, the Matlab language employs the . operator as a modifier for the * operator. However, I'm unaware of any mechanisms in the c++ language that allow operators to be modified like this. Are there any clean workarounds for this behavior?
Here are some things I've thought about already:
- operator overloads allow extra template parameters. However, I'm not entirely sure how to take advantage of this in this context. For instance, something that might be nice (though, in practice, I am not sure there is a valid syntax to achieve this):
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????
}
- Using SFINAE/Concepts/if constexpr and traits to modify binary expression types or wrap binary expression types. Syntax:
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
- Create a free binary function. Possible syntaxes:
Hadamard<Multiplication>(mat1, mat2);
Hadamard_Multiplication(mat1, mat2);
- Using member functions. Syntax:
mat1.hadamard_multiplication(mat2);
None of these seem to have syntax quite as elegant as Matlab's:
mat1 .* mat2;
Are there any techniques available to come close to an operator modifier syntax that I can consider? Or any general techiques to make the usage syntax less verbose? If not, is there any notion that something could be included in future versions of C++ that may be of any use here?