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 typename
s 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
.