C ++ 20 std :: common_reference的目的是什么?


Answers:


46

common_reference 从我的努力出发,提出了可容纳代理迭代器的STL迭代器的概念化。

在STL中,迭代器具有两种相关的特殊类型:referencevalue_type。前者是迭代器的返回类型operator*,而value_typeis是序列元素的(非常量,非引用)类型。

通用算法通常需要执行以下操作:

value_type tmp = *it;

...所以我们知道这两种类型之间一定存在某种关系。对于非代理迭代器,关系很简单:reference始终为value_type,可选为const和引用限定。早期定义该InputIterator概念的尝试要求该表达式*it可转换为const value_type &,并且对于大多数有趣的迭代器而言已足够。

我希望C ++ 20中的迭代器比这更强大。例如,考虑zip_iterator在锁步中迭代两个序列的a的需求。取消引用a时zip_iterator,将获得pair两个迭代器reference类型的临时类型。因此,zip'ing a vector<int>和a vector<double>将具有以下关联类型:

zip迭代器的referencepair<int &, double &>
zip迭代器的value_typepair<int, double>

如您所见,仅通过添加顶级cv-和ref限定条件,这两种类型就不会相互关联。但是,让两种类型任意不同会让人感到错误。显然这里有一些关系。但是两者之间的关系是什么,在迭代器上运行的通用算法可以安全地假设这两种类型呢?

在C ++ 20中的答案是,对于任何有效的迭代器类型,代理与否,其种类reference &&value_type &共享一个共同的参考。换句话说,对于某些迭代器,it有某种类型CR可以使以下格式正确:

void foo(CR) // CR is the common reference for iterator I
{}

void algo( I it, iter_value_t<I> val )
{
  foo(val); // OK, lvalue to value_type convertible to CR
  foo(*it); // OK, reference convertible to CR
}

CR是通用参考。所有算法都可以依赖这种类型存在的事实,并可以std::common_reference用来计算它。

因此,这就是common_referenceC ++ 20中STL中扮演的角色。通常,除非您正在编写通用算法或代理迭代器,否则可以放心地忽略它。它可以确保您的迭代器履行其合同义务。


编辑:OP还要求一个示例。这有点做作,但是假设它是C ++ 20,并且为您提供了一个随机访问r类型的范围R,您sort对该范围一无所知,并且想要该范围。

进一步想象一下,由于某种原因,您想使用单态比较函数,例如std::less<T>。(也许您已经对范围进行了类型擦除,还需要对比较函数进行类型擦除,然后将其传递给virtual?,再进行一次拉伸。)应该Tstd::less<T>哪里?为此,您将使用common_reference,或根据iter_common_reference_t它实现的帮助程序。

using CR = std::iter_common_reference_t<std::ranges::iterator_t<R>>;
std::ranges::sort(r, std::less<CR>{});

即使range r具有代理迭代器,也可以保证工作。


2
也许我很稠密,但是您能说明一下zip-pair示例中的通用参考吗?
happydave '19

4
理想的情况下,pair<T&,U&>pair<T,U>&将有一个共同的参考,这将是简单的pair<T&,U&>。但是,对于std::pair,即使从原则上讲这种转换是合理的,也没有从pair<T,U>&pair<T&,U&>的转换。(顺便说一下,这就是为什么我们zip在C ++ 20中没有视图的原因。)
Eric Niebler

4
@EricNiebler:“ 顺便说一下,这就是为什么我们在C ++ 20中没有zip视图。 ”是否pair出于某些原因为什么必须使用zip迭代器,而不是可以专门为其目的设计的类型? ,并根据需要进行适当的隐式转换?
Nicol Bolas

5
@Nicol Bolas无需使用std::pair;任何具有适当转换的适当成对类型都可以,并且range-v3定义了这种成对类型。在委员会上,LEWG不喜欢在标准库中添加几乎但不是全部的类型std::pair(无论是否规范)的想法,而无需首先对简单std::pair工作的利弊进行尽职调查。
埃里克·尼布尔

3
tuple,,pair ,- - 。具有这个不错的功能,您可以使用和来访问元素。结构化绑定有助于处理s的某些尴尬,但并非全部。tomatotoMAHtopair.first.secondtuple
Eric Niebler
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.