【问题标题】:Is there a trait or any convention to check if a range or a `view_facade` that owns things? (e.g. getlines)是否有一个特征或任何约定来检查一个范围或一个“view_facade”是否拥有东西? (例如 getlines)
【发布时间】:2023-04-07 22:09:01
【问题描述】:

给定

auto empty_line = [](auto& str){ return str.size() == 0; };

因为ranges::getlines 返回一个拥有 view_facade,它拥有一个用于其前端迭代器的缓冲区。

所以我们有义务在传递给算法之前将这种范围设为左值

auto line_range1 = ranges::getlines(std::cin);
auto iter1 = ranges::find_if_not(line_range1,empty_line);
auto input1 = std::stoi(*iter1);

还有一种很酷的保护机制,可以防止所有取消引用迭代器的 at-time 已经破坏的数据,并使这些尝试编译时错误。

因此,当拥有 view_facade 作为 rvalue 传递到算法时,保护会在取消引用时进行。

这不会编译。

auto iter2 = ranges::find_if_not(ranges::getlines(std::cin),empty_line);
// at this point the `owning` range destroyed, 
// so as the buffer we (should've) hold (before!).

// So this won't compile
// auto input2 = std::stoi(*iter2);

错误为:

<source>:19:29: error: no match for 'operator*' (operand type is 'ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >')
     auto input2 = std::stoi(*iter2);
                         ^~~~~~

这也不会编译。

// Won't compile
// auto input3 = std::stoi(*ranges::find_if_not(ranges::getlines(std::cin),
//                                              empty_line)
//                        );

错误为:

<source>:22:29: error: no match for 'operator*' (operand type is 'ranges::v3::safe_iterator_t<ranges::v3::getlines_range> {aka ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >}')
     auto input3 = std::stoi(*ranges::find_if_not(ranges::getlines(std::cin),empty_line));
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

godbolt.org/g/gF6nYx


我的问题是,除了文档之外,是否有任何特征或任何类型的范围约定来检查范围类型是否拥有

也许,像constexpr bool is_owning_v(Rng&amp;&amp;)

【问题讨论】:

  • 是 std::ranges::borrowed_range 你在找什么?
  • @mmackliet 我猜借用的_range“概念”代表非拥有模型,如 string_view 和 span 中的模型。当然,包括那些在“视图”中。因此,borrowed_range 范围可以自然地用作右值,就像 string_view 一样,因为某个地方的某个人在使用 borrowed_range 之前已经将它作为左值拥有。
  • @mmackliet 相反,ranges::getlines 本身确实拥有一行,并且不能用作问题中的右值迭代器源。
  • @mmackliet 还有一件事,borrowed_range 概念确实包括“std::is_lvalue_reference_v”。所以这个“borrowed_range”与 string_view 的不同之处在于,在一个锚定为左值本身的范围之后,从它返回迭代器是安全的,因为某个地方之前有人拥有它,在这种情况下是它的左值。
  • 好的,那么如果 std::ranges::enable_borrowed_range 为假,那不就意味着该类型是一个拥有范围吗?

标签: c++ range traits range-v3


【解决方案1】:

std::ranges::enable_borrowed_range 会告诉你范围类型是否拥有。见P2017R1。要实现您描述的功能,您可以这样做:

template <typename Rng>
constexpr bool is_owning_v(Rng&&)
{
  return !std::ranges::enable_borrowed_range<std::remove_cvref_t<Rng>>;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多