我想编写一个代理类,该类具有模板值,并且可以与可以与模板进行比较的任何类进行比较。
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;
};
Run Code Online (Sandbox Code Playgroud)
例如,由于这是合法代码:
bool compare(std::string first, std::string_view second) {
return first == second;
}
Run Code Online (Sandbox Code Playgroud)
我也希望这是合法的:
bool compare(std::string first, Proxy<std::string_view> second) {
return first == second;
}
Run Code Online (Sandbox Code Playgroud)
但只是为了澄清起见,这应该适用于可以比较的任何类,或者可以进行隐式转换以便进行比较。我可以定义一个条件模板来检查这两种情况吗?
由于您的标准本质上是像like这样的表达式_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; }
Run Code Online (Sandbox Code Playgroud)
它可能不是很干,因为我们需要重复两次表达式,但这是执行SFINAE的相当简单的方法,这是一个主要优点。
要注意的另一件事是,我们不希望递归地考虑第二个重载,这可能在比较两个代理时发生。因此,我们需要另一个SFINAE条件,enable_if用来阐明老式的方式,以在Ua 为时放弃重载Proxy。这依赖于C ++ 14功能,通过该功能可以按声明顺序检查替换。将其放在首位可防止递归first == second._value。