I have a Vector
class which represents a 2D vector. It is templated to allow any numerical type to be used for the x and y components. As an example, one of the arithmetic operators I overload is *
for multiplying a vector with a scalar:
template <typename T, typename U>
inline const Vector<T> operator*(const Vector<T>& vector, U scalar) {
return Vector<T>(vector.x * scalar, vector.y * scalar);
}
(I also have a function with the parameters in the opposite order to allow scalar * Vector
in addition to Vector * scalar
).
As you can see, I use <T, U>
instead of simply <T>
so that the scalar doesn't have to be the same type as the Vector. When I didn't do this, surprisingly Vector<double> * int
wouldn't compile (I thought the int would automatically widen).
In any case, I don't simply want to return a Vector<T>
. I want to mimic the built-in types and return whichever has higher precision, T
or U
. So for example, Vector<int> * double => Vector<double>
while Vector<double> * short => Vector<double>
.
Is this possible?
You can use common_type
or decltype
to cook up something that gives you the resulting type; and then you have to create the actual vector:
template <typename A, typename B>
std::vector<typename std::common_type<A, B>::type>
operator*(std::vector<A> const & v, B const & x)
{
std::vector<typename std::common_type<A, B>::type> res;
res.reserve(v.size());
for (A a : v) res.push_back(a * x);
return res;
}
Using decltype
, you can get at the result type via:
decltype(std::declval<A>() * std::declval<B>())
For both std::common_type
and std::declval
you need to #include <type_traits>
.
With delayed return types (auto
and ->
) you can use decltype
directly on the function arguments, but using std::declval
feels a bit more hygienic, since it doesn't require you to furnish an actual instance of your type (and thus it is applicable even in situations where this isn't possible).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With