14

关于概念 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 提供所有比较运算符<, <=, >, >=, ==, !=。但是,在 C++ 的整个生命周期中,std::sort只需要<提供运算符!这是cppreference所说的std::sort

按升序对范围 [first, last) 中的元素进行排序。不保证保留相等元素的顺序。第一个版本使用 operator< 来比较元素,第二个版本使用给定的比较函数对象 comp。

那么,这是否意味着在未来带有概念的 C++ 中v,类型为std::vector<T>whereT仅提供operator<std::sort(v.begin(), v.end())将编译,而std::sort(v)不会编译?这听起来很疯狂。

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

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

4

1 回答 1

11

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

Ranges TS 版本的sortrequires Sortable,其比较类默认为std::less<>. 但是,这似乎对其参数的类型提出std::less<>::operator()了要求。TotallyOrdered这就是它的来源。P0021R0 (PDF)中有关于此的注释:

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

重点补充。围绕此的一般问题似乎是 on-hold,等待其他语言功能(例如仅基于operator<或某些此类的所有其他运算符的隐式创建)。

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


还应该注意的是,随着C++20中“宇宙飞船运算符”的引入(我们最早可以看到 Ranges TS 集成到标准中),整个讨论实际上变得毫无意义。类中的一个简单声明,突然你的类型是完全有序的。auto operator<=>(const MyType &) = default;

于 2016-01-05T19:25:52.177 回答