使用'+='运算符统一实现c++'+'运算符
Unified implementation of c++ '+' operator using '+=' operator
例如,我有 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!");
...
}
但它不会隐藏其他 类 的模板运算符的声明。因此,这种方法再次导致歧义。
如何实现这样一个统一的运算符+,但只为这两种特定类型定义它?
您可以应用 SFINAE, use std::enable_if
with std::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);
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
.
的工业强度版本
例如,我有 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!");
...
}
但它不会隐藏其他 类 的模板运算符的声明。因此,这种方法再次导致歧义。
如何实现这样一个统一的运算符+,但只为这两种特定类型定义它?
您可以应用 SFINAE, use std::enable_if
with std::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);
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
.