简体   繁体   English

C++ 范围视图迭代器和运算符->

[英]C++ ranges view iterators and operator->

If I perform a transform view operation I noticed that the view iterator does not support the operator->.如果我执行变换视图操作,我注意到视图迭代器不支持运算符->。 So in code terms所以在代码方面

void transform_view( )
{
    struct Z { int a; };

    std::ranges::single_view view { Z { 99 } };

    auto transform_view { std::ranges::views::transform( view, []( auto const& z ){ return Z { z.a + 10 }; } ) };

    // The operator-> does not compile here as there is none defined
    // auto transform_view_first_value { transform_view.begin( )->a };
}

This is "as expected" as the standard in 24.7.6.3 which defines range.transform.iterator does not have an operator->.这是“预期的”,因为 24.7.6.3 中定义 range.transform.iterator 的标准没有运算符->。

I found this a bit surprising and tried to understand why it would not have one.我觉得这有点令人惊讶,并试图理解为什么它没有。 I could not find and overiew in the standard or various web places of what is generally expected of view iterators and why in particular there is no operator-> on at least some of them.我无法在标准或各种 web 中找到和概述视图迭代器的一般预期内容,以及为什么特别是至少其中一些没有 operator-> 的原因。

Does anyone know the answer or a good source of information on this?有谁知道答案或这方面的良好信息来源?

Simplifying, the prototype for the operator-> is:简化一下, operator->的原型是:

T* operator->();

In order to create this operator, you must be able to return a pointer to T and this pointer must be valid after you return from the operator.为了创建这个运算符,你必须能够返回一个指向 T 的指针,并且这个指针在你从运算符返回后必须有效。 So, the iterator must store a temporary object for that pointer and control its life cycle.因此,迭代器必须为该指针存储一个临时的 object 并控制其生命周期。

This would create some problems:这会产生一些问题:

  • Iterators are assumed to be cheap to store, but now they may contain a hidden copy of T.假设迭代器的存储成本低,但现在它们可能包含 T 的隐藏副本。
  • It goes against one of the design rationales: ranges cannot own elements .它违背了设计原理之一: 范围不能拥有元素
  • One of the design guidelines for ranges is that adaptors are lazy evaluated , so the object would be created when the operator-> is called.范围的设计准则之一是适配器是惰性求值的,因此 object 将在调用operator->时创建。 Every call to the operator should destroy the internal object and return a new pointer.对运算符的每次调用都应销毁内部 object 并返回一个新指针。 If we decide to keep the object as a cache, we must add more logic to the iterator to control the life cycle and invalidation of the object.如果我们决定将 object 保留为缓存,则必须在迭代器中添加更多逻辑来控制 object 的生命周期和失效。

It also raises some questions that must be answered by the standard: Who owns that object?它还提出了一些标准必须回答的问题:谁拥有 object? Is it safe to modify it?修改它安全吗? What happens when the iterator is copied?当迭代器被复制时会发生什么? What happens when the iterator is moved?移动迭代器时会发生什么? When is the pointer invalidated?什么时候指针失效?

I think operator-> was not added because it makes the implementation more difficult, but it does not add any improvement: you can use operator* to achieve the same behaviour.我认为未添加operator->是因为它使实现更加困难,但它没有增加任何改进:您可以使用operator*来实现相同的行为。 However, this operator returns a copy of T, so the owner of the object and its life cycle is clear.但是,这个运算符返回了 T 的副本,因此 object 的所有者及其生命周期是明确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM