std::views::filter
結合されたストリーム/範囲での使用に問題があります。ここで何が間違っているのかわかりません。要素が適切な(コピー/移動)セマンティクスで渡されない可能性があると思います。参照ラッパーを使用する必要があります。
#include <ranges>
int main(int argc_, char* argv_[]) {
auto r1 = std::views::single(42);
// create a nested range to have something to join
auto r2 = r1 | std::views::transform([](auto& e_) { return std::ranges::single_view{e_}; });
auto r3 = r2 | std::views::join;
// case #1: single -> transform -> join -> filter
{
auto r4a = r3 | std::views::filter([](auto e_) { return true; });
// ERROR: missing 'iterator_category'
for (int i : r4a) { }
}
// case #2: single -> transform -> join -> transform
{
auto r4b = r3 | std::views::transform([](auto e) { return e; });
// OK: it compiles
for (int i : r4b) { }
}
return 0;
}
行 #17 には、次のエラー メッセージが表示されます。
$ g++ --version
g++ (Rev6, Built by MSYS2 project) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ test.cpp -g -std=c++20
In file included from test.cpp:1:
d:/Programs/msys64/mingw64/include/c++/10.2.0/ranges: In instantiation of 'static constexpr auto std::ranges::filter_view<_Vp, _Pred>::_Iterator::_S_iter_cat() [with _Vp = std::ranges::join_view<std::ranges::transform_view<std::ranges::single_view<int>, main(int, char**)::<lambda(auto:13&)> > >; _Pred = main(int, char**)::<lambda(auto:14)>]':
d:/Programs/msys64/mingw64/include/c++/10.2.0/ranges:1473:48: required from 'struct std::ranges::filter_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::single_view<int>, main(int, char**)::<lambda(auto:13&)> > >, main(int, char**)::<lambda(auto:14)> >::_Iterator'
test.cpp:17:20: required from here
d:/Programs/msys64/mingw64/include/c++/10.2.0/ranges:1455:10: error: no type named 'iterator_category' in 'struct std::iterator_traits<std::ranges::join_view<std::ranges::transform_view<std::ranges::single_view<int>, main(int, char**)::<lambda(auto:13&)> > >::_Iterator<false> >'
1455 | using _Cat = typename iterator_traits<_Vp_iter>::iterator_category;
| ^~~~
d:/Programs/msys64/mingw64/include/c++/10.2.0/ranges:1456:18: error: no type named 'iterator_category' in 'struct std::iterator_traits<std::ranges::join_view<std::ranges::transform_view<std::ranges::single_view<int>, main(int, char**)::<lambda(auto:13&)> > >::_Iterator<false> >'
1456 | if constexpr (derived_from<_Cat, bidirectional_iterator_tag>)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
d:/Programs/msys64/mingw64/include/c++/10.2.0/ranges:1458:23: error: no type named 'iterator_category' in 'struct std::iterator_traits<std::ranges::join_view<std::ranges::transform_view<std::ranges::single_view<int>, main(int, char**)::<lambda(auto:13&)> > >::_Iterator<false> >'
1458 | else if constexpr (derived_from<_Cat, forward_iterator_tag>)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
d:/Programs/msys64/mingw64/include/c++/10.2.0/ranges:1459:34: error: inconsistent deduction for auto return type: 'std::bidirectional_iterator_tag' and then 'std::forward_iterator_tag'
1459 | return forward_iterator_tag{};
| ^
驚いたことに、結合されたストリームで変換アダプターを使用しても問題はありません。
範囲の実装を見てみましたが、さらに疑問が生じました。範囲の反復子 (上記の r1...r4) にはiterator_concepts
およびiterator_category
メンバーの typedef がありますが、これらは一貫していないようです:
// r2) check member types directly
static_assert(std::is_same_v<typename decltype(r2.begin())::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<typename decltype(r2.begin())::iterator_category, std::input_iterator_tag>);
// r2) check member types via iterator_traits
// why is it undefined?
// static_assert(std::is_same_v<typename std::iterator_traits<decltype(r2.begin())>::iterator_concept, ? >);
static_assert(std::is_same_v<typename std::iterator_traits<decltype(r2.begin())>::iterator_category, std::input_iterator_tag>);
// r3) check member types directly
static_assert(std::is_same_v<typename decltype(r3.begin())::iterator_concept, std::input_iterator_tag>);
static_assert(std::is_same_v<typename decltype(r3.begin())::iterator_category, std::input_iterator_tag>);
// r3) check member types via iterator_traits
// why are these undefined?
// static_assert(std::is_same_v<typename std::iterator_traits<decltype(r3.begin())>::iterator_concept, ? >);
// static_assert(std::is_same_v<typename std::iterator_traits<decltype(r3.begin())>::iterator_category, ? >);
17 行目で for ループを実行する方法はありますか?