为什么 std::compare_three_way 不是模板结构/函子

zjy*_*qs 3 c++ c++20

例如,比较的std::less定义为模板结构

template< class T = void >
struct less;
Run Code Online (Sandbox Code Playgroud)

Whilestd::compare_three_way被定义为一个普通的结构体,它operator()是一个模板函数。(来自 MSVC 的代码)

struct compare_three_way {
    template <class _Ty1, class _Ty2>
        requires three_way_comparable_with<_Ty1, _Ty2> // TRANSITION, GH-489
    constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
        noexcept(noexcept(_STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right))) /* strengthened */ {
        return _STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right);
    }

    using is_transparent = int;
};
Run Code Online (Sandbox Code Playgroud)

那么为什么不是std::compare_three_way模板结构呢?

template <class _Ty1, class _Ty2>
    requires three_way_comparable_with<_Ty1, _Ty2>
struct compare_three_way {
    constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const; 
};
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我能代替std::less<T>通过std::three_way_compare在自己的执行容器,像Comparer<T>在C#。

eer*_*ika 7

原始std::less(及其朋友)的比较定义如下:

bool operator()( const T& lhs, const T& rhs ) const;
Run Code Online (Sandbox Code Playgroud)

由于此函数调用运算符不是模板,因此它只能比较用于实例化std::less模板的类型的对象。

在后来的语言修订版中,这些比较器通过专门化进行了扩展,std::less<>以通过对函数调用运算符本身进行模板化来支持比较不同类型的对象:

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

这在很大程度上淘汰了std::less<T>大多数用例中的同构版本 ( ),因为它是等效的,或者由于不强制转换为通用类型而更高效。保留旧的同类比较器以实现向后兼容性。

异构查找在std::compare_three_way提出时是一个存在的东西,因此从未引入同构版本。

要在模板中使用它,就像std::less<T>std::set<T>

您可以使用std::compare_three_waystd::set<T>std::set<U>等(比喻)就像你可以使用std::less<>。你(可能)不需要std::less<T>也不 std::less<U>- 也不std::compare_three_way<T>存在。