英文:
C++20 range get value by index
问题
我想访问范围的第一个值:
#include <stdio.h>
#include <ranges>
#include <algorithm>
using namespace std;
int main()
{
auto rg = views::split("hello there!", ' ') | views::transform([](auto word)->char{return word[0];}) ;
for (char c : rg)
printf("%c", c);
return 0;
}
应该输出字符串"ht",但在使用C++20 g++编译器(g++12)时出现编译错误。
英文:
I want to access the first value from a range:
#include <stdio.h>
#include <ranges>
#include <algorithm>
using namespace std;
int main()
{
auto rg = views::split("hello there!", ' ') | views::transform([](auto word)->char{return word[0];}) ;
for (char c : rg)
printf("%c", c);
return 0;
}
should print out the string "ht", but there is a compile error using C++20 g++ compiler (g++12)
main.cpp: In instantiation of ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’:
/usr/include/c++/11/bits/invoke.h:61:36: required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40: required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26: required from here
**main.cpp:16:99: error: no match for ‘operator[]’ (operand types are ‘std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type’ and ‘int’)**
16 | auto rg = views::split("hello there!", ' ') | views::transform([](auto word)->char{return word[0];}) ;
| ~~~~^
In file included from /usr/include/c++/11/ranges:46,
from main.cpp:10:
/usr/include/c++/11/bits/ranges_util.h:153:9: note: candidate: ‘template requires random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<_Derived>::operator[](std::ranges::range_difference_t<_Range>) [with _Range = _Range; _Derived = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
153 | operator[](range_difference_t<_Range> __n)
| ^~~~~~~~
/usr/include/c++/11/bits/ranges_util.h:153:9: note: template argument deduction/substitution failed:
/usr/include/c++/11/bits/ranges_util.h:153:9: note: constraints not satisfied
In file included from /usr/include/c++/11/ranges:37,
from main.cpp:10:
/usr/include/c++/11/concepts: In substitution of ‘template<class _Range> requires random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type>::operator[]<_Range>(std::ranges::range_difference_t<_Range>) [with _Range = std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]’:
main.cpp:16:99: required from ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
/usr/include/c++/11/bits/invoke.h:61:36: required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40: required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26: required from here
/usr/include/c++/11/concepts:67:13: required for the satisfaction of ‘derived_from<typename std::__detail::__iter_concept_impl<_Iter>::type, std::bidirectional_iterator_tag>’ [with _Iter = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_InnerIter<false>]
/usr/include/c++/11/bits/iterator_concepts.h:649:13: required for the satisfaction of ‘bidirectional_iterator<decltype (std::ranges::__cust_access::__begin(declval<_Container&>()))>’ [with _Tp = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:642:13: required for the satisfaction of ‘bidirectional_range<_Tp>’ [with _Tp = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:647:13: required for the satisfaction of ‘random_access_range<_Range>’ [with _Range = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/concepts:67:28: note: ‘std::bidirectional_iterator_tag’ is not a base of ‘std::forward_iterator_tag’
67 | concept derived_from = __is_base_of(_Base, _Derived)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/ranges:46,
from main.cpp:10:
main.cpp: In instantiation of ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’:
/usr/include/c++/11/bits/invoke.h:61:36: required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40: required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26: required from here
/usr/include/c++/11/bits/ranges_util.h:158:9: note: candidate: ‘template requires random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<_Derived>::operator[](std::ranges::range_difference_t<_Range>) const [with _Range = _Range; _Derived = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
158 | operator[](range_difference_t<_Range> __n) const
| ^~~~~~~~
/usr/include/c++/11/bits/ranges_util.h:158:9: note: template argument deduction/substitution failed:
/usr/include/c++/11/bits/ranges_util.h:158:9: note: constraints not satisfied
In file included from /usr/include/c++/11/ranges:37,
from main.cpp:10:
/usr/include/c++/11/concepts: In substitution of ‘template<class _Range> requires random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type>::operator[]<_Range>(std::ranges::range_difference_t<_Range>) const [with _Range = std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]’:
main.cpp:16:99: required from ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
/usr/include/c++/11/bits/invoke.h:61:36: required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40: required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26: required from here
/usr/include/c++/11/concepts:67:13: required for the satisfaction of ‘derived_from<typename std::__detail::__iter_concept_impl<_Iter>::type, std::bidirectional_iterator_tag>’ [with _Iter = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_InnerIter<false>]
/usr/include/c++/11/bits/iterator_concepts.h:649:13: required for the satisfaction of ‘bidirectional_iterator<decltype (std::ranges::__cust_access::__begin(declval<_Container&>()))>’ [with _Tp = const std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:642:13: required for the satisfaction of ‘bidirectional_range<_Tp>’ [with _Tp = const std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:647:13: required for the satisfaction of ‘random_access_range<_Range>’ [with _Range = const std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/concepts:67:28: note: ‘std::bidirectional_iterator_tag’ is not a base of ‘std::forward_iterator_tag’
67 | concept derived_from = __is_base_of(_Base, _Derived)
|
答案1
得分: 4
错误消息指向/usr/include/c++/11/ranges
,这表明您正在使用的是libstdc++版本11,而不是12。这个版本没有实现P2210R2。
在P2210R2之前,split_view
的元素类型最多只能是forward_range
,它不支持operator[]
。
P2210R2将旧的split_view
重命名为lazy_split_view
,并添加了一个新的split_view
,其元素类型可以模拟更强的范围概念。当底层范围是random_access_range
时,它支持operator[]
。因此,当实现P2210R2时,代码将正确工作。
英文:
The error message points to /usr/include/c++/11/ranges
, which suggests that you are using libstdc++ version 11, not 12. This version does not implement P2210R2.
Prior to P2210R2, the element type of split_view
can at most be a forward_range
, which does not ever support operator[]
.
P2210R2 renamed the old split_view
to lazy_split_view
, and added a new split_view
whose element type can model stronger range concepts. It supports operator[]
when the underlying range is a random_access_range
. Thus the code works correctly when P2210R2 is implemented.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论