I am implementing some matrix operations for my templated matrix<T>
and matrix_view<T>
.
At first I had
template <typename T, typename U>
matrix<common_type_t<T, U>> operator (matrix_view<T>, matrix_view<U>);
and expected it to work also for matrix
matrix<int> a, b;
auto c = a b;
because there is a converting constructor from matrix<T>
to matrix_view<T>
.
But it didn't work, because of the "Type deduction does not consider implicit conversions" rule.
So I added another overload
template <typename T, typename U>
matrix<common_type_t<T, U>> operator (matrix<T>, matrix<U>);
But the story is still not over, for operator
between matrix<T>
and matrix_view<T>
, I need to define another two overloads to make them work.
Now I wonder if I have to define all four overloads for every matrix operation. That's a lot of boilerplate code. And indeed the number of overloads needed grows exponentially with the number of types involved, if I am to add some other types in the future.
Is there any solution to this problem? Preferably only requiring me to define the first overload.
CodePudding user response:
Use a concept:
template<typename C>
concept matrix_c = requires(C const& c) { [] <typename ... X>(matrix<X ...> const&) {}(c); }
|| requires(C const& c) { [] <typename ... X>(matrix_view<X ...> const&) {}(c); }
auto operator (matrix_c auto&& m1, matrix_c auto&& m2);
This solution will work for all combinations of matrix_view
and matrix
.
Note that the concept can be simplified if you use, e.g., a common base class matrix_base
, as it's usual in expression template code. It'll work, however, also for completely unrelated classes.