使用 enable_if 添加重载运算符 ==
Adding overload operator == with enable_if
我有一个工作模板 class 点,其中有 operator==
.
的重载
由于浮点数比较,我试图为浮点数添加 enable_if
的第二个重载以使用几乎相等的函数。
这是我的尝试:
template<typename T>
class Point2D
{
public:
Point2D(T x, T y);
Point2D& operator= (const Point2D& point);
bool operator==(const Point2D& point) const;
bool operator!=(const Point2D& point) const;
};
template<typename T>
Point2D<T>::Point2D(T x, T y) : x_(x), y_(y)
{
}
template<typename T>
Point2D<T>& Point2D<T>::operator=(const Point2D& point)
{
if(this != &point)
{
x_ = point.x_;
y_ = point.y_;
}
return *this;
}
template<typename T>
bool Point2D<T>::operator==(const Point2D& point) const
{
return (x_ == point.x_) && (y_ == point.y_);
}
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
Point2D<T>::operator==(const Point2D& point) const
{
return Traits::almost_equal(x_, point.x_) &&
Traits::almost_equal(y_, point.y_);
}
注:
这是一个简化的例子。
代码实际上可以在没有 enable_if 重载的情况下工作
我必须将声明和实现分开(都在.h中),所以请按原样参考代码。
编译器给我的错误是
error: prototype for typename std::enable_if<std::is_floating_point<_Tp>::value, bool>::type Point2D<T>::operator==(const Point2D<T>&) const
does not match any in class Point2D<T>
Point2D<T>::operator==(const Point2D& point) const
^
error: candidate is: bool Point2D<T>::operator==(const Point2D<T>&)
const bool Point2D<T>::operator==(const Point2D& point) const
^
我不明白错误指的是什么。
错误很明显 - 您的定义与您的声明不符。您需要在原型和定义中使用完全相同的 enable_if
。此外,您的 enable_if
将不起作用,因为它需要在 替换 (SFINAE) 期间发生。
为了提高可读性,您可以定义别名并使用 trailing return 类型:
template<typename T>
class Point2D
{
template <typename U>
using EnableIfFloat =
typename std::enable_if<std::is_floating_point<U>::value, bool>::type;
public:
Point2D(T x, T y);
template <typename U = T>
auto operator==(const Point2D& point) const -> EnableIfFloat<U>&;
bool operator==(const Point2D& point) const;
bool operator!=(const Point2D& point) const;
};
定义:
template<typename T>
template<typename U>
auto Point2D<T>::operator==(const Point2D& point) const -> EnableIfFloat<U>&
{
return Traits::almost_equal(x_, point.x_) &&
Traits::almost_equal(y_, point.y_);
}
真的,只是不要那样做。改为这样做:
template<typename T>
class Point2D
{
bool equals(const Point2D& other, std::true_type is_floating_point ) const;
bool equals(const Point2D& other, std::false_type is_floating_point ) const;
public:
Point2D(T x, T y);
Point2D& operator= (const Point2D& point);
bool operator==(const Point2D& point) const;
bool operator!=(const Point2D& point) const;
};
现在:
template<typename T>
bool Point2D<T>::operator==(const Point2D& point) const
{
return this->equals(point, std::is_floating_point<T>{});
}
template<class T>
bool Point2D<T>::equals(const Point2D& point, std::false_type /*is_floating_point*/ ) const {
return (x_ == point.x_) && (y_ == point.y_);
}
template<class T>
bool Point2D<T>::equals(const Point2D& point, std::true_type /*is_floating_point*/ ) const {
return Traits::almost_equal(x_, point.x_) &&
Traits::almost_equal(y_, point.y_);
}
这是代码调度。它比 SFINAE enable-if stuff 更干净、更容易,编译时间也更少。
我有一个工作模板 class 点,其中有 operator==
.
由于浮点数比较,我试图为浮点数添加 enable_if
的第二个重载以使用几乎相等的函数。
这是我的尝试:
template<typename T>
class Point2D
{
public:
Point2D(T x, T y);
Point2D& operator= (const Point2D& point);
bool operator==(const Point2D& point) const;
bool operator!=(const Point2D& point) const;
};
template<typename T>
Point2D<T>::Point2D(T x, T y) : x_(x), y_(y)
{
}
template<typename T>
Point2D<T>& Point2D<T>::operator=(const Point2D& point)
{
if(this != &point)
{
x_ = point.x_;
y_ = point.y_;
}
return *this;
}
template<typename T>
bool Point2D<T>::operator==(const Point2D& point) const
{
return (x_ == point.x_) && (y_ == point.y_);
}
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
Point2D<T>::operator==(const Point2D& point) const
{
return Traits::almost_equal(x_, point.x_) &&
Traits::almost_equal(y_, point.y_);
}
注:
这是一个简化的例子。
代码实际上可以在没有 enable_if 重载的情况下工作
我必须将声明和实现分开(都在.h中),所以请按原样参考代码。
编译器给我的错误是
error: prototype for typename std::enable_if<std::is_floating_point<_Tp>::value, bool>::type Point2D<T>::operator==(const Point2D<T>&) const does not match any in class Point2D<T> Point2D<T>::operator==(const Point2D& point) const ^ error: candidate is: bool Point2D<T>::operator==(const Point2D<T>&) const bool Point2D<T>::operator==(const Point2D& point) const ^
我不明白错误指的是什么。
错误很明显 - 您的定义与您的声明不符。您需要在原型和定义中使用完全相同的 enable_if
。此外,您的 enable_if
将不起作用,因为它需要在 替换 (SFINAE) 期间发生。
为了提高可读性,您可以定义别名并使用 trailing return 类型:
template<typename T>
class Point2D
{
template <typename U>
using EnableIfFloat =
typename std::enable_if<std::is_floating_point<U>::value, bool>::type;
public:
Point2D(T x, T y);
template <typename U = T>
auto operator==(const Point2D& point) const -> EnableIfFloat<U>&;
bool operator==(const Point2D& point) const;
bool operator!=(const Point2D& point) const;
};
定义:
template<typename T>
template<typename U>
auto Point2D<T>::operator==(const Point2D& point) const -> EnableIfFloat<U>&
{
return Traits::almost_equal(x_, point.x_) &&
Traits::almost_equal(y_, point.y_);
}
真的,只是不要那样做。改为这样做:
template<typename T>
class Point2D
{
bool equals(const Point2D& other, std::true_type is_floating_point ) const;
bool equals(const Point2D& other, std::false_type is_floating_point ) const;
public:
Point2D(T x, T y);
Point2D& operator= (const Point2D& point);
bool operator==(const Point2D& point) const;
bool operator!=(const Point2D& point) const;
};
现在:
template<typename T>
bool Point2D<T>::operator==(const Point2D& point) const
{
return this->equals(point, std::is_floating_point<T>{});
}
template<class T>
bool Point2D<T>::equals(const Point2D& point, std::false_type /*is_floating_point*/ ) const {
return (x_ == point.x_) && (y_ == point.y_);
}
template<class T>
bool Point2D<T>::equals(const Point2D& point, std::true_type /*is_floating_point*/ ) const {
return Traits::almost_equal(x_, point.x_) &&
Traits::almost_equal(y_, point.y_);
}
这是代码调度。它比 SFINAE enable-if stuff 更干净、更容易,编译时间也更少。