首页 > 解决方案 > 为什么 std::compare_three_way 不是模板结构/函子

问题描述

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

template< class T = void >
struct less;

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;
};

那么为什么不是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; 
};

顺便说一句,我可以在我自己的容器实现中替换为,比如std::less<T>在C# 中。std::three_way_compareComparer<T>

标签: c++c++20

解决方案


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

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

由于此函数调用运算符不是模板,它只能比较用于实例化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));
    

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

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

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

您可以使用std::compare_three_wayin std::set<T>std::set<U>(象征性地),就像您可以使用std::less<>. 你(可能)不需要std::less<T>也不 std::less<U>- 也不std::compare_three_way<T>存在。


推荐阅读