Using
auto empty_line = [](auto& str){ return str.size() == 0; };
we can do this:
auto line_range_with_first_non_empty =
ranges::view::drop_while(ranges::getlines(std::cin),empty_line);
auto input1 = std::stoi(*line_range_with_first_non_empty.begin());
and we can also do this:
auto line_range2 = ranges::getlines(std::cin);
auto iter2 = ranges::find_if_not(line_range2,empty_line);
auto input2 = std::stoi(*iter2);
Unfortunately, when I try to shorten version above into:
auto iter3 = ranges::find_if_not(ranges::getlines(std::cin),empty_line);
// auto input3 = std::stoi(*iter3);
I get an error:
<source>:22:29: error: indirection requires pointer operand ('ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >' invalid)
auto input3 = std::stoi(*iter3);
^~~~~~
I thought it's because of that infinite range but I was wrong.
auto sin = std::istringstream{"\n\n\nmy line\n"};
auto iter4 = ranges::find_if_not(ranges::getlines(sin),empty_line);
// Error when deref.
// auto input4 = std::stoi(*iter4);
This produces the same error.
<source>:27:29: error: indirection requires pointer operand ('ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >' invalid)
auto input4 = std::stoi(*iter4);
^~~~~~
Why can't I dereference when ranges::find_if
takes a range as rvalue?
Does ranges::getlines
return a range? If so, are ranges supposed to own things?
find_if_not
return an iterator into a temporary range. The range would be destroyed, leaving the iterator dangling, before it could be used, leading to undefined behavior. The ranges proposal protects against this situation, turning it into a compile-time error. – Igor Tandetnikgetlines
view will cache the most recently read line in an internalstd::string
says member. – Eric Niebler