[英]Why isn't `std::compare_three_way` a `std::strict_weak_order`?
[英]Why std::compare_three_way is not a template struct/functor
例如std::less
的比較被定義為模板結構
template< class T = void >
struct less;
而std::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::three_way_compare
替換std::less<T>
,比如 C# 中的Comparer<T>
。
原始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::set<T>
std::less<T>
std::set<T>
您可以在std::set<T>
和std::set<U>
等中使用std::compare_three_way
(比喻),就像您可以使用std::less<>
。 您(可能)不需要std::less<T>
或std::less<U>
- 也不需要不存在的std::compare_three_way<T>
。
由於看起來std::compare_three_way
執行轉發,因此當模板參數用於struct
時它無法工作。 C++ 標准部分 13.10.3.2 §3 :
轉發引用是對不代表類模板的模板參數的cv 非限定模板參數的右值引用(在類模板參數推導期間 ([over.match.class.deduct]))。
因此,這里_Ty1&&
和_Ty2&&
只是右值引用,沒有辦法正確轉發它們:
template <class _Ty1, class _Ty2>
requires three_way_comparable_with<_Ty1, _Ty2>
struct compare_three_way {
constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const;
};
上面聲明的模板結構只接受右值表達式作為其操作數,這不會太有用。 使這個struct
可用的唯一方法是使參數成為const
引用。 MSVC 實現者選擇了轉發方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.