C++20范围通过索引获取值

huangapple go评论78阅读模式
英文:

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 &lt;stdio.h&gt;
#include &lt;ranges&gt;
#include &lt;algorithm&gt;
using namespace std;

int main()
{
    auto rg = views::split(&quot;hello there!&quot;, &#39; &#39;) | views::transform([](auto word)-&gt;char{return word[0];}) ;
    
    for (char c : rg)
        printf(&quot;%c&quot;, 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 &gt;::_OuterIter::value_type]’:
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&amp;&amp;, _Args&amp;&amp; ...) [with _Res = char; _Fn = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::type std::__invoke(_Callable&amp;&amp;, _Args&amp;&amp; ...) [with _Callable = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}; typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::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 &gt;::_OuterIter::value_type’ and ‘int’)**
16 |     auto rg = views::split(&quot;hello there!&quot;, &#39; &#39;) | views::transform([](auto word)-&gt;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&lt;_Range&gt; constexpr decltype(auto) std::ranges::view_interface&lt;_Derived&gt;::operator[](std::ranges::range_difference_t&lt;_Range&gt;) [with _Range = _Range; _Derived = std::ranges::split_view, std::ranges::single_view &gt;::_OuterIter::value_type]’
153 |         operator[](range_difference_t&lt;_Range&gt; __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&lt;class _Range&gt;  requires  random_access_range&lt;_Range&gt; constexpr decltype(auto) std::ranges::view_interface&lt;std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type&gt;::operator[]&lt;_Range&gt;(std::ranges::range_difference_t&lt;_Range&gt;) [with _Range = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type]’:
main.cpp:16:99:   required from ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view &gt;::_OuterIter::value_type]’
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&amp;&amp;, _Args&amp;&amp; ...) [with _Res = char; _Fn = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::type std::__invoke(_Callable&amp;&amp;, _Args&amp;&amp; ...) [with _Callable = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}; typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::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&lt;typename std::__detail::__iter_concept_impl&lt;_Iter&gt;::type, std::bidirectional_iterator_tag&gt;’ [with _Iter = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_InnerIter&lt;false&gt;]
/usr/include/c++/11/bits/iterator_concepts.h:649:13:   required for the satisfaction of ‘bidirectional_iterator&lt;decltype (std::ranges::__cust_access::__begin(declval&lt;_Container&amp;&gt;()))&gt;’ [with _Tp = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type]
/usr/include/c++/11/bits/ranges_base.h:642:13:   required for the satisfaction of ‘bidirectional_range&lt;_Tp&gt;’ [with _Tp = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type]
/usr/include/c++/11/bits/ranges_base.h:647:13:   required for the satisfaction of ‘random_access_range&lt;_Range&gt;’ [with _Range = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::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 &gt;::_OuterIter::value_type]’:
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&amp;&amp;, _Args&amp;&amp; ...) [with _Res = char; _Fn = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::type std::__invoke(_Callable&amp;&amp;, _Args&amp;&amp; ...) [with _Callable = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}; typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::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&lt;_Range&gt; constexpr decltype(auto) std::ranges::view_interface&lt;_Derived&gt;::operator[](std::ranges::range_difference_t&lt;_Range&gt;) const [with _Range = _Range; _Derived = std::ranges::split_view, std::ranges::single_view &gt;::_OuterIter::value_type]’
158 |         operator[](range_difference_t&lt;_Range&gt; __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&lt;class _Range&gt;  requires  random_access_range&lt;_Range&gt; constexpr decltype(auto) std::ranges::view_interface&lt;std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type&gt;::operator[]&lt;_Range&gt;(std::ranges::range_difference_t&lt;_Range&gt;) const [with _Range = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type]’:
main.cpp:16:99:   required from ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view &gt;::_OuterIter::value_type]’
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&amp;&amp;, _Args&amp;&amp; ...) [with _Res = char; _Fn = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::type std::__invoke(_Callable&amp;&amp;, _Args&amp;&amp; ...) [with _Callable = main()::&lt;lambda(auto:19)&gt;&amp;; _Args = {std::ranges::split_view&lt;std::ranges::ref_view&lt;const char [13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type}; typename std::__invoke_result&lt;_Functor, _ArgTypes&gt;::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&lt;typename std::__detail::__iter_concept_impl&lt;_Iter&gt;::type, std::bidirectional_iterator_tag&gt;’ [with _Iter = std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_InnerIter&lt;false&gt;]
/usr/include/c++/11/bits/iterator_concepts.h:649:13:   required for the satisfaction of ‘bidirectional_iterator&lt;decltype (std::ranges::__cust_access::__begin(declval&lt;_Container&amp;&gt;()))&gt;’ [with _Tp = const std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type]
/usr/include/c++/11/bits/ranges_base.h:642:13:   required for the satisfaction of ‘bidirectional_range&lt;_Tp&gt;’ [with _Tp = const std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::value_type]
/usr/include/c++/11/bits/ranges_base.h:647:13:   required for the satisfaction of ‘random_access_range&lt;_Range&gt;’ [with _Range = const std::ranges::split_view&lt;std::ranges::ref_view&lt;const char[13]&gt;, std::ranges::single_view&lt;char&gt; &gt;::_OuterIter&lt;false&gt;::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.

huangapple
  • 本文由 发表于 2023年7月20日 16:52:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定