查找模板相等运算符

Finding template equality operators

本文关键字:运算符 查找      更新时间:2023-10-16

我想写一个代理类,它接受一个模板值,可以与模板可以比较的任何类进行比较。

template <class T>
class Proxy {
public:
Proxy(T value) : _value(value) {}
template <class U> // this should exist only if the T == U operator is defined
bool operator==(U const& other) const  { return _value == other; }
template <class U> // this should exist only if U == T is defined
friend bool operator==(U const& first, Proxy<T> const& second) const  { return first == second._value; }
private:
T _value;
};

例如,由于这是法律代码:

bool compare(std::string first, std::string_view second) {
return first == second;
}

我也希望这是合法的:

bool compare(std::string first, Proxy<std::string_view> second) {
return first == second;
}

但澄清一下,这应该适用于任何可以比较的类,或者可以隐式转换以便进行比较的类。我可以定义一个模板条件来检查这两种情况吗?

由于您的标准本质上是像_value == other这样的表达式是否格式正确,因此您可以依靠表达式 SFINAE 来测试它。

template <class U> // this should exist only if the T == U operator is defined
auto operator==(U const& other) const -> decltype(_value == other)
{ return _value == other; }
template <class U, std::enable_if_t<!std::is_same<U, Proxy>::value, int> = 0> // this should exist only if U == T is defined
friend auto operator==(U const& first, Proxy const& second) -> decltype(first == second._value)
{ return first == second._value; }

它可能不是很干燥,因为我们需要重复两次表达式,但这是一种相当简单的方法来做 SFINAE,这是一个主要的优点。

另一件需要注意的事情是,我们不希望递归地考虑第二个重载,这可能会在比较两个代理时发生。因此,我们需要另一个SFINAE条件,用enable_if拼写出老式的方式,以便在UProxy时丢弃过载。这依赖于 C++14 功能,即按声明顺序检查替换项。将其放在首位可防止first == second._value中的递归。