我有一个代表2D矢量的Vector
类。模板允许任何数字类型用于 x 和 y 组件。例如,我重载的算术运算符之一是*
,用于将向量与标量相乘:
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);
}
(除了scalar * Vector
之外,我还有一个函数,其参数顺序相反,只允许Vector * scalar
。
正如您所看到的,我使用<T, U>
而不是简单地<T>
,因此标量不必与Vector相同。当我没有这样做时,令人惊讶的是Vector<double> * int
无法编译(我认为int会自动加宽)。
无论如何,我不想简单地返回Vector<T>
。我想模仿内置类型并返回具有更高精度的T
或U
。例如,Vector<int> * double => Vector<double>
Vector<double> * short => Vector<double>
。
这可能吗?
答案 0 :(得分:5)
您可以使用common_type
或decltype
来制作能够为您提供结果类型的内容;然后你必须创建实际的向量:
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;
}
使用decltype
,您可以通过以下方式获取结果类型:
decltype(std::declval<A>() * std::declval<B>())
对于std::common_type
和std::declval
,您需要#include <type_traits>
。
使用延迟返回类型(auto
和->
),您可以直接在函数参数上使用decltype
,但使用std::declval
感觉更卫生,因为它不会不要求你提供你的类型的实际实例(因此即使在不可能的情况下也适用)。
答案 1 :(得分:3)
这有两个解决方案。在Pre C ++ 11中,您可以编写如下模板:
template <typename T, typename U>
struct WhatWillItBe {
typedef T result_t;
};
template <typename T>
struct WhatWillItBe<T, double> {
typedef double result_t;
};
// ... lots more
等。并编写很多的专业化,然后你可以使用它来查找返回类型,例如:
template <typename T, typename U>
inline const Vector<typename WhatWillItBe<T,U>::result_t> operator*(const Vector<T>& vector, U scalar) {
return Vector<typename WhatWillItBe<T,U>::result_t>(vector.x * scalar, vector.y * scalar);
}
或者C ++ 11简单明了,您可以为返回类型编写auto
并使用->
在函数的其余部分之后指定返回类型:
template <typename T, typename U>
inline auto operator*(const Vector<T>& vector, U scalar) -> Vector<decltype(vector.x*scalar)> {
return Vector<decltype(vector.x*scalar)>(vector.x * scalar, vector.y * scalar);
}
允许您使用decltype
作为函数的返回类型,根据vector.x * scalar
自然促销的内容进行设置。