C ++ 20 std :: common_reference的目的是什么? [英] What is the purpose of C++20 std::common_reference?

查看:188
本文介绍了C ++ 20 std :: common_reference的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 20引入了 std::common_reference .目的是什么?有人可以举一个使用它的例子吗?

C++20 introduces std::common_reference. What is its purpose? Can someone give an example of using it?

推荐答案

common_reference是出于我的努力,提出了可容纳代理迭代器的STL迭代器的概念.

common_reference came out of my efforts to come up with a conceptualization of STL's iterators that accommodates proxy iterators.

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

In the STL, iterators have two associated types of particular interest: reference and value_type. The former is the return type of the iterator's operator*, and the value_type is the (non-const, non-reference) type of the elements of the sequence.

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

Generic algorithms often have a need to do things like this:

value_type tmp = *it;

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

... so we know that there must be some relationship between these two types. For non-proxy iterators the relationship is simple: reference is always value_type, optionally const and reference qualified. Early attempts at defining the InputIterator concept required that the expression *it was convertible to const value_type &, and for most interesting iterators that is sufficient.

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

I wanted iterators in C++20 to be more powerful than this. For example, consider the needs of a zip_iterator that iterates two sequences in lock-step. When you dereference a zip_iterator, you get a temporary pair of the two iterators' reference types. So, zip'ing a vector<int> and a vector<double> would have these associated types:

zip迭代器的reference:pair<int &, double &>
zip迭代器的value_type:pair<int, double>

zip iterator's reference : pair<int &, double &>
zip iterator's value_type: pair<int, double>

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

As you can see, these two types are not related to each other simply by adding top-level cv- and ref qualification. And yet letting the two types be arbitrarily different feels wrong. Clearly there is some relationship here. But what is the relationship, and what can generic algorithms that operate on iterators safely assume about the two types?

在C ++ 20中,答案是对于任何有效迭代器类型(是否具有代理),类型reference &&value_type &共享通用引用.换句话说,对于某些迭代器it,有某种类型的CR可以使以下格式正确:

The answer in C++20 is that for any valid iterator type, proxy or not, the types reference && and value_type & share a common reference. In other words, for some iterator it there is some type CR which makes the following well-formed:

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进行计算.

CR is the common reference. All algorithms can rely on the fact that this type exists, and can use std::common_reference to compute it.

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

So, that is the role that common_reference plays in the STL in C++20. Generally, unless you are writing generic algorithms or proxy iterators, you can safely ignore it. It's there under the covers ensuring that your iterators are meeting their contractual obligations.

OP也要求提供示例.这有点做作,但是假设它是C ++ 20,并且您得到了类型为R的随机访问范围r,对此您一无所知,并且您想sort范围.

The OP also asked for an example. This is a little contrived, but imagine it's C++20 and you are given a random-access range r of type R about which you know nothing, and you want to sort the range.

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

Further imagine that for some reason, you want to use a monomorphic comparison function, like std::less<T>. (Maybe you've type-erased the range, and you need to also type-erase the comparison function and pass it through a virtual? Again, a stretch.) What should T be in std::less<T>? For that you would use common_reference, or the helper iter_common_reference_t which is implemented in terms of it.

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

即使范围r具有代理迭代器,也可以保证工作.

That is guaranteed to work, even if range r has proxy iterators.

这篇关于C ++ 20 std :: common_reference的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆