如何将修改应用到局部范围并 return 它?

How do I apply modifications to a locally scoped range and return it?

下面的代码,当使用 --std=c++20 -D_GLIBCXX_DEBUG 在 g++-11.3 下编译并执行时,会产生一个关于迭代器的奇怪的运行时错误。我不太确定这是什么意思,但我怀疑它与向量 range 超出范围有关 test() returns: range 不被移动或复制,而不是管道运算符 returns 只是保留对 range.

的引用
#include <ranges>
#include <unordered_set>
#include <vector>

auto to_unordered_set(auto && range) {
    using r_type = std::ranges::range_value_t<decltype(range)>;
    auto common = range | std::views::common;
    return std::unordered_set<r_type>(std::ranges::begin(common), std::ranges::end(common));
}

auto test() {
    std::vector<int> range {1,2,3,4,5};
    return range | std::ranges::views::transform([](auto x) { return x%2; });
}

int main() {
    auto y = to_unordered_set(test());
    return 0;
}

/*
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/debug/safe_iterator.h:195:
In function:
    __gnu_debug::_Safe_iterator<_Iterator, _Sequence, 
    _Category>::_Safe_iterator(__gnu_debug::_Safe_iterator<_Iterator, 
    _Sequence, _Category>&&) [with _Iterator = 
    __gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, 
    std::allocator<int> > >; _Sequence = std::__debug::vector<int>; 
    _Category = std::forward_iterator_tag]

Error: attempt to copy-construct an iterator from a singular iterator.

Objects involved in the operation:
    iterator "this" @ 0x0x7ffea2b7a8c0 {
      type = __gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, std::allocator<int> > > (mutable iterator);
      state = singular;
    }
    iterator "other" @ 0x0x7ffea2b7a820 {
      type = __gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, std::allocator<int> > > (mutable iterator);
      state = singular;
      references sequence with type 'std::__debug::vector<int, std::allocator<int> >' @ 0x0x7ffea2b7a8b0
    }
*/

有没有办法让这样的东西起作用?我基本上想转换/过滤/加入/等..一个范围和return它(整个事物的copy/move得到returned,范围和任何修改都应用到它)。

首先,由于std::vector本身就是common_rangetransform_view也会是common_range,所以这里使用views::common是多余的。

其次更重要的是,range是一个局部变量,所以一旦离开test()就会被销毁,这使得test()return成为了[=13] =] 持有悬空指针。

Is there anyway to get something like this to work?

感谢P2415,你可以直接return一个transform_view应用到一个右值vector,这将构造owning_view 将原始 vector 内容的所有权转移给自己,这将不再导致悬挂。

#include <ranges>
#include <unordered_set>
#include <vector>

auto to_unordered_set(auto && range) {
  using r_type = std::ranges::range_value_t<decltype(range)>;
  return std::unordered_set<r_type>(
           std::ranges::begin(range), std::ranges::end(range));
}

auto test() {
  std::vector<int> range {1,2,3,4,5};
  return std::move(range) | 
    std::ranges::views::transform([](auto x) { return x%2; });
}

int main() {
  auto y = to_unordered_set(test());
}

Demo