问题
I want to split, reverse, and then join a string using range-v3. However, code below won't compile.
#include <range/v3/all.hpp>
#include <iostream>
using namespace ranges;
int main(int argc, char *argv[])
{
auto str = std::string("abc.def.ghi");
auto sv = str
| view::split('.')
| view::reverse
| view::join('.');
std::cout<<sv;
return 0;
}
Compiler output:
error: invalid operands to binary expression ('decltype(pipeable_access::impl<view<reverse_fn> >::pipe(static_cast<ranges::v3::split_view<ranges::v3::iterator_range<std::_String_iterator<std::_String_val<std::_Simple_types<char> > >, std::_String_iterator<std::_String_val<std::_Simple_types<char> > > >, ranges::v3::view::split_fn::element_pred<std::basic_string<char, std::char_traits<char>, std::allocator<char> > &> > &&>(arg), pipe))' (aka 'void') and 'decltype(make_view(view_access::impl<join_fn>::bind(this->view_, static_cast<char &&>(ts))))' (aka 'view<ranges::v3::detail::pipeable_binder<std::_Binder<std::_Unforced, ranges::v3::view::join_fn &, const std::_Ph<1> &, char> > >'))
range\v3\view\any_view.hpp:60: candidate function not viable: cannot convert argument of incomplete type 'decltype(pipeable_access::impl<view<reverse_fn> >::pipe(static_cast<ranges::v3::split_view<ranges::v3::iterator_range<std::_String_iterator<std::_String_val<std::_Simple_types<char> > >, std::_String_iterator<std::_String_val<std::_Simple_types<char> > > >, ranges::v3::view::split_fn::element_pred<std::basic_string<char, std::char_traits<char>, std::allocator<char> > &> > &&>(arg), pipe))' (aka 'void') to 'ranges::v3::category' for 1st argument
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\regex:1219: candidate function not viable: cannot convert argument of incomplete type 'decltype(pipeable_access::impl<view<reverse_fn> >::pipe(static_cast<ranges::v3::split_view<ranges::v3::iterator_range<std::_String_iterator<std::_String_val<std::_Simple_types<char> > >, std::_String_iterator<std::_String_val<std::_Simple_types<char> > > >, ranges::v3::view::split_fn::element_pred<std::basic_string<char, std::char_traits<char>, std::allocator<char> > &> > &&>(arg), pipe))' (aka 'void') to 'std::_Node_flags' for 1st argument
range\v3\utility\functional.hpp:725: candidate template ignored: substitution failure [with Arg = void, Pipe = ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Binder<std::_Unforced, ranges::v3::view::join_fn &, const std::_Ph<1> &, char> > >, _concept_requires_724 = false, $3 = nullptr]: cannot form a reference to 'void'
range\v3\utility\functional.hpp:734: candidate template ignored: requirement 'false || (is_pipeable<void>() && is_pipeable<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Binder<std::_Unforced, ranges::v3::view::join_fn &, const std::_Ph<1> &, char> > > >())' was not satisfied [with Pipe0 = void, Pipe1 = ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Binder<std::_Unforced, ranges::v3::view::join_fn &, const std::_Ph<1> &, char> > >, _concept_requires_733 = false]
Found a way of doing this:
auto temp_container = str
| view::split('.')
| ::ranges::to_vector
| action::reverse
;
std::string output = temp_container
| view::all
| view::join('.')
;
Any better ideas?
回答1:
view::split
returns either a an input range or a forward range depending on the adapted range. view::reverse
requires at least a bidirectional range in order to iterate it backwards.
In principle it would be possible to implement a split_view
that is a bidirectional range. The problem is that the constructor would already need a complete traversal of the adapted range to find the last element, making it an o(n) operation. And as far as I know the construction of views is required to be o(1).
来源:https://stackoverflow.com/questions/57090147/why-cant-i-reverse-a-split-range-using-range-v3