使用 Ranges-v3 视图::join保留双向性
Retain bidirectionality with Ranges-v3 view::join
我在使用(惊人的)Ranges-v3库的view::join
函数对象时遇到了一些困难。我的客户端代码依赖于 back 方法的存在(并且非常感谢随机访问迭代器)来获得范围集合的聚合视图。
在查看相关文档后,似乎back
方法与join_view类模板的实例化兼容,但我无法将其实例化。
#include <iostream>
#include <vector>
#include <range/v3/all.hpp>
struct Foo{
std::vector<int> i = {1,2,3,4};
const std::vector<int>& data() const { return this->i; }
};
int main(){
std::vector< Foo > foos = { Foo(), Foo(), Foo() };
auto data = []( auto&& foo ){ return foo.data() | ranges::view::all; };
auto flat = foos | ranges::view::transform(data) | ranges::view::join;
std::cout << flat.back() << std::endl; // compiler error
}
编译器错误消息的相关位是:
main.cpp:17:28: error: no matching function for call to 'ranges::v3::join_view<ranges::v3::transform_view<ranges::v3::range<__gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> >, __gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> > >, main()::<lambda(auto:1&&)> >, void>::back()'
std::cout << flat.back() << std::endl; // compiler error
/usr/local/include/range/v3/range_interface.hpp:116:34: note: candidate: template<class D, int _concept_requires_115, typename std::enable_if<((_concept_requires_115 == 43) || ((std::is_same<D, ranges::v3::join_view<ranges::v3::transform_view<ranges::v3::range<__gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> >, __gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> > >, main()::<lambda(auto:1&&)> >, void> >() && ranges::v3::concepts::models<ranges::v3::concepts::BoundedView, T>()) && ranges::v3::concepts::models<ranges::v3::concepts::BidirectionalView, T>())), int>::type <anonymous> > ranges::v3::range_reference_t<D> ranges::v3::range_interface<Derived, Inf>::back() [with D = D; int _concept_requires_115 = _concept_requires_115; typename std::enable_if<((_concept_requires_115 == 43) || ((std::is_same<D, Derived>() && ranges::v3::concepts::models<ranges::v3::concepts::BoundedView, D>()) && ranges::v3::concepts::models<ranges::v3::concepts::BidirectionalView, D>())), int>::type <anonymous> = <enumerator>; Derived = ranges::v3::join_view<ranges::v3::transform_view<ranges::v3::range<__gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> >, __gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> > >, main()::<lambda(auto:1&&)> >, void>; bool Inf = false]
range_reference_t<D> back()
/usr/local/include/range/v3/range_interface.hpp:115:17: error: no type named 'type' in 'struct std::enable_if<false, int>'
CONCEPT_REQUIRES_(Same<D, Derived>() && BoundedView<D>() && BidirectionalView<D>())>
第一个要求似乎是强制正确使用CRTP,这是满足的。因此,join_view
违反了BoundedView
或BidirectionalView
概念(或两者兼而有之)。我能够迅速消除前者的可能性。
auto flat = foos
| ranges::view::transform(data)
| ranges::view::join
| ranges::view::bounded;
std::cout << flat.back() << std::endl; // compiler error
在这种情况下,flat
满足BoundedView
概念,但错误消息保持不变。
为了验证BidirectionalView
,我尝试检查join_view
的迭代器,但遇到的(可疑的)是一个错误。
auto it = flat.begin();
std::cout << *it << std::endl; // correct
++it; std::cout << *it << std::endl; // correct
--it; std::cout << *it << std::endl; // doesn't actually decrement
auto other = --it;
std::cout << *it << ' ' << *other << std::endl; // also doesn't decrement
我已经写了一个实时版本,以便于检查。
有没有人运气实例化双向join_view
?关于如何在不复制基础数据的情况下实现类似行为的任何建议?
Range-v3 的join
视图满足InputRange
,但不能满足Forward
或任何更强的东西。它与如何完成联接有关。在迭代内部范围时,需要将范围存储在某个位置。某处位于join_view
对象的成员中。换句话说,join_view
在迭代时会发生突变。因此,它无法对任何强于Input
的范围类别进行建模。
相关文章:
- 有根的二进制搜索树.保留与其父级的链接
- 为多个会话保留XPtr
- 在std::thread中,joinable()然后join()线程安全吗
- 保留对其他类的成员函数的引用
- 指针保留字符串
- 是否有内置方法可以强制转换为不同的基础类型,但保留常量限定符?
- 如何让 GCC/Clang 在保留标识符上出错
- 必须为 C++20 协程帧保留多少内存?
- 如何将一个窗口保留在另一个应用程序窗口的前面
- 使用 char 分隔符解析C++中的字符串,但将可重复的字符保留为每个解析的子字符串 (C++ STL) 中的分隔符
- join() 失败,如果在线程内部调用 io_context.run()
- 局部变量保留函数中的值
- 保留函数指针模板参数
- 变量超出范围后如何保留向量值?
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 当为可变性配置时,boost::heap::d_ary_heap 保留的额外 std::list 的目的是什么?
- 如何使用 swig 修改类构造函数以保留对其中一个构造函数参数的引用?
- 即使在使用 delete[] 后仍保留的元素
- 如何在成为指向基类的指针后保留对子类方法的使用?
- 使用 Ranges-v3 视图::join保留双向性