C ++ 20引入std::common_reference
。目的是什么?有人可以举一个使用它的例子吗?
C ++ 20引入std::common_reference
。目的是什么?有人可以举一个使用它的例子吗?
Answers:
common_reference
从我的努力出发,提出了可容纳代理迭代器的STL迭代器的概念化。
在STL中,迭代器具有两种相关的特殊类型:reference
和value_type
。前者是迭代器的返回类型operator*
,而value_type
is是序列元素的(非常量,非引用)类型。
通用算法通常需要执行以下操作:
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
迭代器的reference
:pair<int &, double &>
zip
迭代器的value_type
:pair<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_reference
C ++ 20中STL中扮演的角色。通常,除非您正在编写通用算法或代理迭代器,否则可以放心地忽略它。它可以确保您的迭代器履行其合同义务。
编辑:OP还要求一个示例。这有点做作,但是假设它是C ++ 20,并且为您提供了一个随机访问r
类型的范围R
,您sort
对该范围一无所知,并且想要该范围。
进一步想象一下,由于某种原因,您想使用单态比较函数,例如std::less<T>
。(也许您已经对范围进行了类型擦除,还需要对比较函数进行类型擦除,然后将其传递给virtual
?,再进行一次拉伸。)应该T
在std::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
具有代理迭代器,也可以保证工作。
pair<T&,U&>
和pair<T,U>&
将有一个共同的参考,这将是简单的pair<T&,U&>
。但是,对于std::pair
,即使从原则上讲这种转换是合理的,也没有从pair<T,U>&
到pair<T&,U&>
的转换。(顺便说一下,这就是为什么我们zip
在C ++ 20中没有视图的原因。)
pair
出于某些原因为什么必须使用zip迭代器,而不是可以专门为其目的设计的类型? ,并根据需要进行适当的隐式转换?
std::pair
;任何具有适当转换的适当成对类型都可以,并且range-v3定义了这种成对类型。在委员会上,LEWG不喜欢在标准库中添加几乎但不是全部的类型std::pair
(无论是否规范)的想法,而无需首先对简单std::pair
工作的利弊进行尽职调查。
tuple
,,pair
,- - 。具有这个不错的功能,您可以使用和来访问元素。结构化绑定有助于处理s的某些尴尬,但并非全部。tomato
to
MAH
to
pair
.first
.second
tuple