【问题标题】:Unified implementation of c++ '+' operator using '+=' operator使用'+='运算符统一实现c++'+'运算符
【发布时间】:2018-09-25 03:13:36
【问题描述】:

例如,我有 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个特定类型定义呢?

【问题讨论】:

    标签: c++ operators


    【解决方案1】:
    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&amp;, rhs const&amp; ) 函数,(C) 定义了 +=

    (C) 太贪心了。

    您也可以使用boost.operators,这是我的add_using_increment 的工业级版本。

    【讨论】:

      【解决方案2】:

      您可以申请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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-23
        • 2013-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-26
        相关资源
        最近更新 更多