为什么Sortable概念需要完全有序的值类型,而std :: sort只需要"小于"可比?

时间:2016-01-05 19:15:13

标签: c++ c++17 c++-concepts

latest paper on concepts N3701中,以下示例包含sort算法:

template<typename Cont>
  requires Sortable<Cont>()
void sort(Cont& cont)

其中Sortable概念定义为

template<typename T>
concept bool Sortable()
{
  return Permutable_container<T>() && Totally_ordered<Value_type<T>>();
}

其中Totally_ordered,毫不奇怪,定义为

template<typename T>
constexpr bool Totally_ordered()
{
  return Weakly_ordered<T>() && Equality_comparable<T>();
}

反过来Equality_comparable定义为

template<typename T>
constexpr bool Equality_comparable()
{
  return requires(T a, T b) {
    {a == b} -> bool;
    {a != b} -> bool;
  };
}

我没有找到Weakly_ordered的定义,但我相信它应该是这样的(我是对的吗?)

template<typename T>
constexpr bool Weakly_ordered()
{
  return requires(T a, T b) {
    {a < b} -> bool;
    {a <= b} -> bool;
    {a > b} -> bool;
    {a >= b} -> bool;
  };
}

在这个定义的底线,如果我想对std::vector<T>进行排序,我需要T提供所有比较运算符<<=,{{ 1}},>>===。但是,在C ++的整个生命周期中,!=只需要提供运算符std::sort!以下是cppreference关于<的说法:

  

按升序对[first,last]范围内的元素进行排序。该   不保证保持相等元素的顺序。首先   版本使用运算符&lt;比较元素,第二个版本   使用给定的比较函数对象comp。

那么,这意味着在未来的C ++中使用概念,std::sort类型为v std::vector<T>只提供Toperator<将编译虽然std::sort(v.begin(), v.end())不会?这听起来很疯狂。

我在Eric Niebler的当前ranges-v3 implementation中检查了这一点,它就像我描述的那样工作。除非提供所有运算符,否则代码不会编译。

另见相关讨论:https://github.com/ericniebler/range-v3/issues/271

1 个答案:

答案 0 :(得分:11)

概念TS没有概念化标准库。这只是一个例子;仅此而已。

sort的Ranges TS版本需要Sortable,默认其比较类为std::less<>。但是,std::less<>::operator()似乎对其参数类型强加TotallyOrdered要求。这就是它的来源。在P0021R0 (PDF)中有关于此的说明:

  

[编者注:删除[utility.arg.requirements]中的表[lessthancomparable]。将LessThanComparable替换为TotallyOrdered(确认这是一个突破性更改,使类型要求更严格)。将[lessthancomparable]的引用替换为[concepts.lib.compare.totallyordered]的引用]

重点补充。围绕此appear to be on-hold的一般性问题,等待其他语言功能(例如仅基于operator<隐藏创建所有其他运算符或其他语言)。

您可以简单地使用(理智)版本的比较功能。或者你可以使用std::sort迭代器版本,它不会使用任何类型的概念。

还应该注意的是,在C ++ 20中the introductionthe "spaceship operator"(最早我们可以看到Ranges TS被整合到标准中),这整个讨论实际上没有实际意义。

中的一个简单auto operator<=>(const MyType &) = default;声明,突然你的类型完全有序。