1

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 ループを実行する方法はありますか?

4

0 に答える 0