std::sort 中的二进制表达式错误(缺少常量)的无效操作数:为什么指定比较运算符可以解决它?

Invalid operands to binary expression error (missing const) in std::sort: Why does specifying the compare operator solve it?

正在考虑:

#include <algorithm>
#include <vector>

struct A {
    double dummy;
    
    bool operator<(const A& a) { ///Here I am missing a `const`
        return dummy < a.dummy;
    }
};

int main()
{
    std::vector<A> a;
    a.push_back({0.9});
    a.push_back({0.4});
    std::sort(a.begin(),a.end());
    return 0;
}

这在 gcc 上编译得很好,但在 clang 上它给出了

/usr/include/c++/v1/algorithm:719:71: error: invalid operands to binary expression ('const A' and 'const A')
    bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}

和一长串失败的实例化。 这是我的最小示例:https://rextester.com/VEO17629

当我找到operator <必须有一个const说明符)时,我终于可以解决它了。

奇怪的是,如果我调用 std::sort 指定运算符 std::less<>():

,错误也会消失
std::sort(a.begin(),a.end(),std::less<>());

为什么指定比较运算符std::less<>()可以解决错误?

Why does specifying the compare operator std::less<>() solve the error?

有趣的是,只有当您使用 std::less<void> (std::less<>) 时它才会编译。 std::less<A> 没有。

std::less<A>::operator():

constexpr bool operator()( const T& lhs, const T& rhs ) const;

std::less<void>::operator() 的签名略有不同,未指定 const T&:

template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
  -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs));

因此,std::less<void>::operator() 可以自由调用非 const operator<


g++ (libstdc++) 和 clang++ (libc++) 之间的区别可以有一些不同的解释。一种是如果 libstdc++std::sort(a.begin(),a.end()) 转发给 std::sort(a.begin(),a.end(), std::less<>{}) 而不是直接使用 operator<

在 C++14 中(您在演示中使用的)[alg.sorting]/1 只是说:“25.4 中的所有操作都有两个版本:一个采用 Compare 和一个使用 operator<.".

没有什么禁止使用std::less<void>调用operator<

在 C++20 中 [sort]/1 甚至还有一个补充,在没有给出比较器时准确指定该行为: "compless{}projidentity{},对于没有这些名称参数的重载。 ”。 clang++/libc++ 在 C++20 模式下不符合这一点。