我有一个涵盖多字段结构的范围。
只能通过运算符 [] 访问字段。
我想对其中一个字段进行替换。
我可以使用基于范围的 for 循环来做到这一点。
有没有更好的方法使用 range::replace() 函数?我正在使用 C++20,但我也很好奇如果需要的话是否可以使用 C++23 来实现。
#include <ranges>
#include <algorithm>
using namespace std;
enum Direction
{
HORIZONTAL,
VERTICAL
};
struct Maille
{
int16_t i, j;
int16_t& operator[](Direction input_direction)
{
switch (input_direction)
{
case HORIZONTAL:
return j;
case VERTICAL:
return i;
}
}
int16_t operator[](Direction input_direction) const
{
switch (input_direction)
{
case HORIZONTAL:
return j;
case VERTICAL:
return i;
}
}
};
int main()
{
Maille tab[2]={
{.i=1,.j=2},
{.i=2,.j=1}
};
for (Maille& m : tab)
{
if (m[HORIZONTAL]==1)
m[HORIZONTAL]=4;
}
ranges::replace(tab | views::transform([](Maille& m){
return m[HORIZONTAL];}),1,4);
return 0;
}
错误信息:
main.cpp: In function ‘int main()’:
main.cpp:52:20: error: no match for call to ‘(const std::ranges::__replace_fn) (std::ranges::transform_view, main():: >, int, int)’
52 | ranges::replace(tab | views::transform([](Maille& m){
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 | return m[HORIZONTAL];}),1,4);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/14/algorithm:63,
from main.cpp:3:
/usr/include/c++/14/bits/ranges_algo.h:782:7: note: candidate: ‘template requires (input_iterator<_Iter>) && (sentinel_for<_Sent, _Iter>) && ((indirectly_writable<_Iter, const _Tp2&>) && (indirect_binary_predicate::__type, const _Tp1*>)) constexpr _Iter std::ranges::__replace_fn::operator()(_Iter, _Sent, const _Tp1&, const _Tp2&, _Proj) const’
782 | operator()(_Iter __first, _Sent __last,
| ^~~~~~~~
/usr/include/c++/14/bits/ranges_algo.h:782:7: note: candidate expects 4 arguments, 3 provided
/usr/include/c++/14/bits/ranges_algo.h:799:7: note: candidate: ‘template requires (input_range<_Range>) && ((indirectly_writable)())), const _Tp2&>) && (indirect_binary_predicate)())), _Proj>::__type, const _Tp1*>)) constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__replace_fn::operator()(_Range&&, const _Tp1&, const _Tp2&, _Proj) const’
799 | operator()(_Range&& __r,
| ^~~~~~~~
/usr/include/c++/14/bits/ranges_algo.h:799:7: note: template argument deduction/substitution failed:
/usr/include/c++/14/bits/ranges_algo.h:799:7: note: constraints not satisfied
In file included from /usr/include/c++/14/bits/stl_iterator_base_types.h:71,
from /usr/include/c++/14/iterator:61,
from /usr/include/c++/14/ranges:43,
from main.cpp:2:
/usr/include/c++/14/bits/iterator_concepts.h: In substitution of ‘template<class _Range, class _Tp1, class _Tp2, class _Proj> requires (input_range<_Range>) && ((indirectly_writable<decltype(std::ranges::__access::__begin((declval<_Container&>)())), const _Tp2&>) && (indirect_binary_predicate<std::ranges::equal_to, typename std::__detail::__projected<decltype(std::ranges::__access::__begin((declval<_Container&>)())), _Proj>::__type, const _Tp1*>)) constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__replace_fn::operator()(_Range&&, const _Tp1&, const _Tp2&, _Proj) const [with _Range = std::ranges::transform_view<std::ranges::ref_view<Maille [2]>, main()::<lambda(Maille&)> >; _Tp1 = int; _Tp2 = int; _Proj = std::identity]’:
main.cpp:52:20: required from here
52 | ranges::replace(tab | views::transform([](Maille& m){
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 | return m[HORIZONTAL];}),1,4);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/iterator_concepts.h:561:13: required for the satisfaction of ‘indirectly_writable<decltype (std::ranges::__access::__begin(declval<_Container&>())), const _Tp2&>’ [with _Range = std::ranges::transform_view<std::ranges::ref_view<Maille[2]>, main::._anon_117>; _Tp2 = int]
/usr/include/c++/14/bits/iterator_concepts.h:561:35: in requirements with ‘_Out&& __o’, ‘_Tp&& __t’ [with _Out = std::ranges::transform_view<std::ranges::ref_view<Maille[2]>, main::._anon_117>::_Iterator<false>; _Tp = const int&]
/usr/include/c++/14/bits/iterator_concepts.h:563:14: note: the required expression ‘*__o =(forward<_Tp>)(__t)’ is invalid
563 | *__o = std::forward<_Tp>(__t);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/iterator_concepts.h:564:34: note: the required expression ‘*(forward<_Out>)(__o)=(forward<_Tp>)(__t)’ is invalid
564 | *std::forward<_Out>(__o) = std::forward<_Tp>(__t);
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/iterator_concepts.h:566:11: note: the required expression ‘const_cast)())&&>(*__o) =(forward<_Tp>)(__t)’ is invalid
565 | const_cast<const iter_reference_t<_Out>&&>(*__o)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
566 | = std::forward<_Tp>(__t);
| ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/iterator_concepts.h:568:11: note: the required expression ‘const_cast)())&&>(*(forward<_Out>)(__o))=(forward<_Tp>)(__t)’ is invalid
567 | const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
568 | = std::forward<_Tp>(__t);
| ^~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set ‘-fconcepts-diagnostics-depth=’ to at least 2 for more detail
main.cpp: In member function ‘int16_t& Maille::operator[](Direction)’:
main.cpp:25:9: warning: control reaches end of non-void function [-Wreturn-type]
25 | }
| ^
出现错误的原因是 lambda 默认按值返回,因此您尝试将其赋值给 prvalue。您可以通过为 lambda 指定返回类型来修复此问题。