创建一个包含升压适配器的自定义范围 class
Creating a custom range class that wraps boost adaptors
我有一个 class 将一些升压变换适配器应用到一个范围(例如,实际上它比这复杂得多):
struct Foo {
auto range() const {
return boost::irange(0, 10)
| boost::adaptors::transformed([] (auto x) { return x * 2; });
}
auto begin() const { return range().begin(); }
auto end() const { return range().end(); }
};
仅此一项就允许我们使用以下范围迭代 Foo
:
for (auto x : Foo()) {
std::cout << num << std::endl;
}
但是,这不能很好地与其他增强适配器或范围操作(如 boost::join
)组合:
auto bad = boost::join(boost::irange(0, 10), Foo());
auto also_bad = Foo() | boost::adaptors::transformed([] (auto x) { return x + 1; });
以上两者都会引发一些讨厌的模板错误。前者(bad
):
In file included from test.cpp:4:
/usr/local/include/boost/range/join.hpp:30:70: error: no type named 'type' in
'boost::range_iterator<const Foo, void>'
BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange1>::type,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/usr/local/include/boost/range/join.hpp:44:28: note: in instantiation of template class
'boost::range_detail::joined_type<const Foo, const boost::integer_range<int> >' requested
here
: public range_detail::joined_type<SinglePassRange1, SinglePassRange2>::type
^
test.cpp:34:16: note: in instantiation of template class 'boost::range::joined_range<const Foo,
const boost::integer_range<int> >' requested here
auto bad = boost::join(Foo(), range);
^
...
而后者(also_bad
):
In file included from test.cpp:1:
In file included from /usr/local/include/boost/range/any_range.hpp:17:
In file included from /usr/local/include/boost/range/detail/any_iterator.hpp:22:
In file included from /usr/local/include/boost/range/detail/any_iterator_wrapper.hpp:16:
In file included from /usr/local/include/boost/range/concepts.hpp:24:
/usr/local/include/boost/range/value_type.hpp:26:70: error: no type named 'type' in
'boost::range_iterator<Foo, void>'
struct range_value : iterator_value< typename range_iterator<T>::type >
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/usr/local/include/boost/range/adaptor/replaced.hpp:109:40: note: in instantiation of template
class 'boost::range_value<Foo>' requested here
BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f )
^
test.cpp:35:27: note: while substituting deduced template arguments into function template
'operator|' [with SinglePassRange = Foo]
auto also_bad = Foo() | boost::adaptors::transformed([] (auto x) { return x * 2; });
^
...
这两个错误似乎都在抱怨 Foo
不是一个范围。我尝试按照建议 添加 operator OutContainer()
和 iterator
/const_iterator
的类型定义,但无济于事。我必须对 Foo
做些什么才能让它很好地处理这些范围操作?
这个错误在这种情况下非常有用。你的类型必须模仿 SinglePassRange
and it does not. There's a page 如何做到这一点,虽然你提供了 begin()
和 end()
,但你没有为 iterator
和 const_iterator
提供类型别名.因此,您不建模 SinglePassRange
.
但是你的代码失败其实很好,因为它也很糟糕。您有 begin()
调用 range().begin()
和 end()
调用 range().end()
。这些是 不同范围 的迭代器。所以这无论如何都是未定义的行为——你不符合 SinglePassRange
.
的语义概念
更简单的解决方案是直接使用 Foo()
。这已经有效:
auto good = boost::join(boost::irange(0, 10), Foo().range());
auto also_good = Foo().range() | boost::adaptors::transformed([] (auto x) { return x + 1; });
这意味着您只需编写一个函数:range()
我有一个 class 将一些升压变换适配器应用到一个范围(例如,实际上它比这复杂得多):
struct Foo {
auto range() const {
return boost::irange(0, 10)
| boost::adaptors::transformed([] (auto x) { return x * 2; });
}
auto begin() const { return range().begin(); }
auto end() const { return range().end(); }
};
仅此一项就允许我们使用以下范围迭代 Foo
:
for (auto x : Foo()) {
std::cout << num << std::endl;
}
但是,这不能很好地与其他增强适配器或范围操作(如 boost::join
)组合:
auto bad = boost::join(boost::irange(0, 10), Foo());
auto also_bad = Foo() | boost::adaptors::transformed([] (auto x) { return x + 1; });
以上两者都会引发一些讨厌的模板错误。前者(bad
):
In file included from test.cpp:4:
/usr/local/include/boost/range/join.hpp:30:70: error: no type named 'type' in
'boost::range_iterator<const Foo, void>'
BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange1>::type,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/usr/local/include/boost/range/join.hpp:44:28: note: in instantiation of template class
'boost::range_detail::joined_type<const Foo, const boost::integer_range<int> >' requested
here
: public range_detail::joined_type<SinglePassRange1, SinglePassRange2>::type
^
test.cpp:34:16: note: in instantiation of template class 'boost::range::joined_range<const Foo,
const boost::integer_range<int> >' requested here
auto bad = boost::join(Foo(), range);
^
...
而后者(also_bad
):
In file included from test.cpp:1:
In file included from /usr/local/include/boost/range/any_range.hpp:17:
In file included from /usr/local/include/boost/range/detail/any_iterator.hpp:22:
In file included from /usr/local/include/boost/range/detail/any_iterator_wrapper.hpp:16:
In file included from /usr/local/include/boost/range/concepts.hpp:24:
/usr/local/include/boost/range/value_type.hpp:26:70: error: no type named 'type' in
'boost::range_iterator<Foo, void>'
struct range_value : iterator_value< typename range_iterator<T>::type >
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/usr/local/include/boost/range/adaptor/replaced.hpp:109:40: note: in instantiation of template
class 'boost::range_value<Foo>' requested here
BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f )
^
test.cpp:35:27: note: while substituting deduced template arguments into function template
'operator|' [with SinglePassRange = Foo]
auto also_bad = Foo() | boost::adaptors::transformed([] (auto x) { return x * 2; });
^
...
这两个错误似乎都在抱怨 Foo
不是一个范围。我尝试按照建议 operator OutContainer()
和 iterator
/const_iterator
的类型定义,但无济于事。我必须对 Foo
做些什么才能让它很好地处理这些范围操作?
这个错误在这种情况下非常有用。你的类型必须模仿 SinglePassRange
and it does not. There's a page 如何做到这一点,虽然你提供了 begin()
和 end()
,但你没有为 iterator
和 const_iterator
提供类型别名.因此,您不建模 SinglePassRange
.
但是你的代码失败其实很好,因为它也很糟糕。您有 begin()
调用 range().begin()
和 end()
调用 range().end()
。这些是 不同范围 的迭代器。所以这无论如何都是未定义的行为——你不符合 SinglePassRange
.
更简单的解决方案是直接使用 Foo()
。这已经有效:
auto good = boost::join(boost::irange(0, 10), Foo().range());
auto also_good = Foo().range() | boost::adaptors::transformed([] (auto x) { return x + 1; });
这意味着您只需编写一个函数:range()