I have a class like this
template <typename T>
class Matrix {
typedef T value_type
...
};
I would like to write a function that needs to deal with different Matrix<T> types but also with arithmetic types (that is why I cannot use Matrix<T1> and Matrix<T2> as template arguments). Inside the function I need a Matrix that has the correct type, if I pass Matrix<T3> and Matrix<T4> for a and b then the type of the Matrix C should be whatever T3 T4 returns (T3 and T4 are arithmetic types).
template <typename T1, typename T2>
auto add(T1&& a, T2&& b);
Matrix<decltype(a(0,0) b(0,0))> C{}; // This works, but I am sure there is a nicer solution
I found one way to do it but I am sure that it is possible to work directly with the types. I tried something like
Matrix<decltype(remove_cvref_t<T1>::value_type remove_cvref_t<T2>::value_type) C;
The idea is to strip off any possible references and access the type of the Matrix via ::value_type. I also tried to sprinkle in some typenames but without success.
CodePudding user response:
No, it's not possible to work directly with the types, but you can use std::declval - a function which returns whatever type you want - to "convert" a type to a value:
template <typename T1, typename T2>
auto add(T1&& a, T2&& b) {
Matrix<decltype(
std::declval<remove_cvref_t<T1>::value_type>()
std::declval<remove_cvref_t<T2>::value_type>()
)> C;
...
}
It's still ugly. If all your matrices have the (0,0) operator then you might find that less ugly, and there's nothing wrong with using it; if you absolutely do need value_type as opposed to whatever (0,0) returns, then you can use std::declval.
std::declval can't be called for real - its only purpose is to be used in expressions that don't actually get evaluated, like inside decltype or noexcept.
