C ++算术运算符重载 - 自动扩展?

时间:2012-02-20 21:08:58

标签: c++ templates generics math operator-overloading

我有一个代表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>。我想模仿内置类型并返回具有更高精度的TU。例如,Vector<int> * double => Vector<double> Vector<double> * short => Vector<double>

这可能吗?

2 个答案:

答案 0 :(得分:5)

您可以使用common_typedecltype来制作能够为您提供结果类型的内容;然后你必须创建实际的向量:

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_typestd::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自然促销的内容进行设置。