微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决C++ 范围视图迭代器和运算符->

如果我执行转换视图操作,我注意到视图迭代器不支持运算符->。所以在代码方面

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 };
}

这是“如预期的”,因为 24.7.6.3 中的标准定义了 range.transform.iterator 没有操作符->。

我觉得这有点令人惊讶,并试图理解为什么它没有。我无法在标准或各种网站中找到和概述视图迭代器的普遍预期,以及为什么特别是在其中至少有一些没有操作符->。

有没有人知道这方面的答案或很好的信息来源?

解决方法

简单来说,operator-> 的原型是:

T* operator->();

为了创建这个运算符,你必须能够返回一个指向 T 的指针,并且这个指针在你从运算符返回后必须是有效的。因此,迭代器必须为该指针存储一个临时对象并控制其生命周期。

这会产生一些问题:

  • 迭代器被认为存储成本低,但现在它们可能包含 T 的隐藏副本。
  • 它违背了设计原理之一:ranges cannot own elements
  • 范围的设计准则之一是 adaptors are lazy evaluated,因此将在调用 operator-> 时创建对象。对操作符的每次调用都应该销毁内部对象并返回一个新指针。如果我们决定将对象作为缓存保留,则必须在迭代器中添加更多逻辑来控制对象的生命周期和失效。

它还提出了一些标准必须回答的问题:谁拥有该对象?修改它是否安全?当迭代器被复制时会发生什么?当迭代器移动时会发生什么?指针什么时候失效?

我认为没有添加 operator-> 是因为它使实现更加困难,但它没有增加任何改进:您可以使用 operator* 来实现相同的行为。但是这个操作符返回的是T的副本,所以对象的拥有者和生命周期是明确的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。