我希望将boost :: optional视为可以包含零个或一个元素的容器。从逻辑上讲,我应该能够为容器创建一个迭代器,并在其上使用boost :: for_each。我的尝试在下面,但无法编译。我已经在GodBolt上尝试过。
以下代码供参考。
#include <boost/optional.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <iostream>
namespace boost {
template <typename OT>
class optional_iterator
: public boost::iterator_facade<optional_iterator<OT>,
typename OT::value_type,
boost::forward_traversal_tag> {
private:
OT m_o;
public:
optional_iterator() : m_o(boost::none) {}
explicit optional_iterator(OT& o) : m_o(o) {}
private:
friend class boost::iterator_core_access;
void increment() { m_o = boost::none; }
bool equal(OT& other) const { return this->m_o == other.m_o; }
typename OT::value_type& dereference() { return *m_o; }
};
template <typename T>
struct optional_iterators {
typedef optional_iterator<boost::optional<T>> iterator;
typedef optional_iterator<boost::optional<T> const> const_iterator;
};
template <class T>
struct range_mutable_iterator<boost::optional<T>> {
typedef typename optional_iterators<T>::iterator type;
};
template <class T>
struct range_const_iterator<boost::optional<T> const> {
typedef typename optional_iterators<T const>::const_iterator type;
};
template <class T>
inline typename optional_iterators<T>::iterator range_begin(
boost::optional<T>& x) {
return typename optional_iterators<T>::iterator(x);
}
template <class T>
inline typename optional_iterators<T>::const_iterator range_begin(
boost::optional<T> const& x) {
return typename optional_iterators<T>::const_iterator(x);
}
template <class T>
inline typename optional_iterators<T>::iterator range_end(boost::optional<T>&x) {
return typename optional_iterators<T>::iterator();
}
template <class T>
inline typename optional_iterators<T>::const_iterator range_end(boost::optional<T> const & x) {
return typename optional_iterators<T>::const_iterator();
}
} // namespace boost
int main() {
auto a = boost::optional<int>(10);
auto rb = range_begin(a);
auto re = range_end(a);
boost::for_each(a, [](int const& i) { std::cout << i; });
}
我相当确定我已经正确实现了范围和迭代器的概念,但是我在gcc 8.1中遇到了以下编译器错误(根据godbolt的说法)
#1 with x86-64 gcc 8.1
In file included from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/size_type.hpp:20,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/size.hpp:21,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/functions.hpp:20,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range.hpp:18,
from <source>:3:
/opt/compiler-explorer/libs/boost_1_64_0/boost/range/concepts.hpp: In instantiation of 'struct boost::SinglePassRangeConcept<boost::optional<int> >':
/opt/compiler-explorer/libs/boost_1_64_0/boost/concept/detail/has_constraints.hpp:32:62: required by substitution of 'template<class Model> boost::concepts::detail::yes boost::concepts::detail::has_constraints_(Model*, boost::concepts::detail::wrap_constraints<Model, (& Model::constraints)>*) [with Model = boost::SinglePassRangeConcept<boost::optional<int> >]'
/opt/compiler-explorer/libs/boost_1_64_0/boost/concept/detail/has_constraints.hpp:42:5: required from 'const bool boost::concepts::not_satisfied<boost::SinglePassRangeConcept<boost::optional<int> > >::value'
/opt/compiler-explorer/libs/boost_1_64_0/boost/concept/detail/has_constraints.hpp:45:31: required from 'struct boost::concepts::not_satisfied<boost::SinglePassRangeConcept<boost::optional<int> > >'
/opt/compiler-explorer/libs/boost_1_64_0/boost/mpl/if.hpp:63:11: required from 'struct boost::mpl::if_<boost::concepts::not_satisfied<boost::SinglePassRangeConcept<boost::optional<int> > >, boost::concepts::constraint<boost::SinglePassRangeConcept<boost::optional<int> > >, boost::concepts::requirement<boost::concepts::failed************ boost::SinglePassRangeConcept<boost::optional<int> >::************> >'
/opt/compiler-explorer/libs/boost_1_64_0/boost/concept/detail/general.hpp:51:8: required from 'struct boost::concepts::requirement_<void (*)(boost::SinglePassRangeConcept<boost::optional<int> >)>'
/opt/compiler-explorer/libs/boost_1_64_0/boost/range/size.hpp:62:9: required from 'UnaryFunction boost::range::for_each(SinglePassRange&, UnaryFunction) [with SinglePassRange = boost::optional<int>; UnaryFunction = main()::<lambda(const int&)>]'
<source>:75:59: required from here
/opt/compiler-explorer/libs/boost_1_64_0/boost/range/concepts.hpp:272:17: error: no type named 'type' in 'struct boost::range_iterator<const boost::optional<int>, void>'
>::type const_iterator;
^~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/libs/boost_1_64_0/boost/concept/assert.hpp:35,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/concept_check.hpp:20,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/concepts.hpp:19,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/size_type.hpp:20,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/size.hpp:21,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range/functions.hpp:20,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/range.hpp:18,
from <source>:3:
/opt/compiler-explorer/libs/boost_1_64_0/boost/range/concepts.hpp:279:9: error: no type named 'type' in 'struct boost::range_iterator<const boost::optional<int>, void>'
BOOST_RANGE_CONCEPT_ASSERT((
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-8.1.0/include/c++/8.1.0/algorithm:62,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/core/swap.hpp:25,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/optional/optional.hpp:27,
from /opt/compiler-explorer/libs/boost_1_64_0/boost/optional.hpp:15,
from <source>:2:
/opt/compiler-explorer/gcc-8.1.0/include/c++/8.1.0/bits/stl_algo.h:3876:5: error: '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = boost::optional_iterator<boost::optional<int> >; _Funct = main()::<lambda(const int&)>]', declared using local type 'main()::<lambda(const int&)>', is used but never defined [-fpermissive]
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
^~~~~~~~
/opt/compiler-explorer/gcc-8.1.0/include/c++/8.1.0/bits/stl_algo.h:3876:5: warning: '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = boost::optional_iterator<boost::optional<int> >; _Funct = main()::<lambda(const int&)>]' used but never defined
Compiler returned: 1
答案 0 :(得分:1)
我会保持简单:
template <typename T> auto make_range(optional<T>& opt) {
T* addr = opt? std::addressof(*opt) : nullptr;
return make_iterator_range(addr, opt? addr+1 : addr);
}
我还没有测试过,但是看起来很简单,也许可以正常工作。