c++ - SFINAE 检查 std::less 是否有效

标签 c++ sfinae

在我的代码中,如果一个对象小于另一个对象,我希望一个操作先于另一个操作发生。但是,如果类型不可比较,则顺序无关紧要。为此,我尝试使用 SFINAE:

template<typename T, typename = decltype(std::declval<std::less<T>>()(std::declval<T>(), std::declval<T>()))> 
bool ComparableAndLessThan(const T& lhs, const T& rhs) {
    return std::less<T>()(lhs, rhs);
}
bool ComparableAndLessThan(...) {
    return false;
}

struct foo {};
int main()
{
    foo a,b;
    if (ComparableAndLessThan(a, b)) {
        std::cout << "a first" << std::endl;
    } else {
        std::cout << "b first" << std::endl;
    }
}

然而,这并没有奏效。如果我创建一个对象而不给它一个 operator< 或 std::less 特化,我会得到这个错误。

error C2678: binary '<': no operator found which takes a left-hand operand of type 'const foo' (or there is no acceptable conversion)
note: could be 'bool std::operator <(const std::error_condition &,const std::error_condition &) noexcept'
note: or       'bool std::operator <(const std::error_code &,const std::error_code &) noexcept'
note: while trying to match the argument list '(const foo, const foo)'
note: while compiling class template member function 'bool std::less<T>::operator ()(const _Ty &,const _Ty &) const'
       with
       [
           T=foo,
           _Ty=foo
       ]

我假设因为声明存在,SFINAE 不会将此视为错误,即使实现会导致错误。有什么方法可以检查 std::less 是否可以用于模板类型?

最佳答案

代码有两个问题。首先很容易修复:默认模板参数不是重载解析的一部分,不应该用于 SFINAE 类型的解析。有一个规范的修复,你制作一个类型为 your_decltype 的非类型模板参数* 并默认为 nullptr .

第二题比较难。即使进行了上述修复,SFINAE 也无法正常工作,因为没有替代错误。 std::less<T>为每个 T定义 , 只是在operator< 时出现编译错误叫做。解决它的一种方法是直接使用 operator<对于你的类型:

template<typename T, 
     decltype(std::declval<T>() < std::declval<T>())* = nullptr> 
bool ComparableAndLessThan(const T& lhs, const T& rhs) {
    return std::less<T>()(lhs, rhs);
}
bool ComparableAndLessThan(...) {
    return false;
}

但它可能并不如您所愿。我不知道如何让它与定义非常广泛的 std::less 一起工作.

关于c++ - SFINAE 检查 std::less 是否有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48953610/

相关文章:

c++ - RawStringFormats 和 Delimeters 'pb' 在 clang 格式中的含义

c++ - C++20 范围的切片 View

c++ - 编译时断言*跨模块*/c,c++

c++ - MSVC 2013 'type': 不是 'std::enable_if<false,void> 的成员

c++ - 根据类型特征专门化强制转换运算符

c++ - 抽一张牌,然后呼唤它

c++ - 在给出错误的函数的for循环中声明整数

c++ - 如果包为空,是否对可变参数包类型执行替换?

c++ - 当方法可用时,我如何专门化模板?

c++ - 在 SFINAE 中将 int 缩小为 bool,gcc 和 clang 之间的输出不同