使用'+ ='运算符统一实现c ++'+'运算符

时间:2018-09-25 03:13:36

标签: c++ operators

例如,我有2种结构:一个2D向量和一个定义了+ =运算符的3D向量:

struct Vector2
{
    double x;
    double y;
    ....
    Vector2& operator+=(const Vector2& vector);
    ....
};

struct Vector3
{
    double x;
    double y;
    double z;
    ....
    Vector3& operator+=(const Vector3& vector);
    ....
};

使用相应的'+ ='运算符为这些结构实现'+'运算符很简单:

Vector2 operator+(const Vector2& vector1, const Vector2& vector2) 
{
    Vector2 result(vector1);
    result += vector2;
    return result;
}

Vector3 operator+(const Vector3& vector1, const Vector3& vector2) 
{
    Vector3 result(vector1);
    result += vector2;
    return result;
}

我想统一这两个功能,并用一个模板功能替换它们:

template <class T>
T operator+(const T& vector1, const T& vector2)
{
    T result(vector1);
    result += vector2;
    return result;
}

但是此函数是如此通用,以致于operator +对于其他类是模棱两可的。 我尝试使用自定义类型特征和static_assert使此模板仅适用于Vector2和Vector3结构:

template <class T>
T operator+(const T& vector1, const T& vector2)
{
    static_assert(suitable_type_for_this_function<T>::value, "Unsupported type!");
    ...
}

但是它不会隐藏其他类的模板运算符的声明。因此,这种方法再次导致模棱两可。

如何实现这种统一的operator +,但仅针对这2种特定类型进行定义?

2 个答案:

答案 0 :(得分:2)

template<class D>
struct add_using_increment {
  using Self=add_using_increment<D>;
  friend D operator+(Self&& lhs, Self const& rhs){
    lhs+=rhs;
    return std::move(lhs.self());
  }
  friend D operator+(Self const& lhs, Self const& rhs){
    return D(lhs.self())+rhs;
  }
private:
  D&self(){ return *static_cast<D*>(this); }
  D const&self()const{ return *static_cast<D const*>(this); }
};

现在只需执行以下操作:

struct Vector2:add_using_increment<Vector2>

或者,您可以使用SFINAE将模板参数限制为(A)是固定集之一,(B)定义了void increment( lhs&, rhs const& )函数,(C)定义了+=在上面。

(C)太贪婪了。

您还可以使用boost.operators,它是我的add_using_increment的工业强度版本。

答案 1 :(得分:1)

您可以应用SFINAE,将std::enable_ifstd::is_same结合使用来约束T上允许的类型。

template <class T>
std::enable_if_t<std::is_same_v<T, Vector2> || std::is_same_v<T, Vector3>, T>
operator+(const T& vector1, const T& vector2);