#ifndef BOOST_RANGE_ADAPTOR_MOVED_HPP #define BOOST_RANGE_ADAPTOR_MOVED_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace range_detail { namespace meta { template struct push_back { typedef typename boost::fusion::result_of::as_vector< typename boost::fusion::result_of::push_back< Sequence , T >::type >::type type; }; } struct invoke_pipe { template struct result; template struct result { typedef decltype( boost::declval() | boost::declval() ) type; }; template inline typename result< invoke_pipe const(Range&&, Adaptor const&) >::type operator()(Range&& rng, Adaptor const& adpt) const { return std::forward(rng) | adpt; } }; // move_forwarder struct move_forwarder {}; // moved_range template class moved_range { public: // types typedef Container container_type; typedef Adaptors adaptors_type; typedef typename boost::fusion::result_of::accumulate< adaptors_type, container_type, invoke_pipe >::type adapted_range_type; typedef typename boost::range_iterator< typename boost::remove_reference::type >::type iterator; typedef typename boost::range_iterator< typename boost::remove_reference::type const >::type const_iterator; // ctors moved_range(moved_range&& other) : cont_(std::move(other.cont_)), adpts_(other.adpts_) {} moved_range(Container&& cont, Adaptors const& adpts) : cont_(std::move(cont)), adpts_(adpts) {} template explicit moved_range( Cont&& cont , typename boost::enable_if< boost::mpl::and_< boost::is_same , typename boost::fusion::result_of::empty::type > >::type* = 0 ) : cont_(std::move(cont)), adpts_() {} // data access Container&& move_container() { return std::move(cont_); } Adaptors const& adaptors() const { return adpts_; } // iterators iterator begin() { if (!adapted_rng_) { adapt(); } return boost::begin(*adapted_rng_); } const_iterator begin() const { if (!adapted_rng_) { adapt(); } return boost::const_begin(*adapted_rng_); } iterator end() { if (!adapted_rng_) { adapt(); } return boost::end(*adapted_rng_); } const_iterator end() const { if (!adapted_rng_) { adapt(); } return boost::const_end(*adapted_rng_); } template friend inline moved_range< Container , typename meta::push_back::type > operator|(moved_range&& rng, Adaptor const& adpt) { return moved_range< Container , typename meta::push_back::type >( std::move(rng.cont_) , boost::fusion::push_back(rng.adpts_, adpt) ); } friend inline moved_range operator|(moved_range&& rng, move_forwarder) { return std::move(rng); } private: // adapting + caching void adapt() const { adapted_rng_ = boost::fusion::accumulate(adpts_, cont_, invoke_pipe()); } // data Container cont_; Adaptors adpts_; mutable boost::optional adapted_rng_; }; // pipe operators for move_forwarder template inline typename boost::disable_if< boost::is_lvalue_reference , moved_range > >::type operator|(Range&& rng, move_forwarder) { return moved_range >(std::move(rng)); } template inline Range& operator|(Range& rng, move_forwarder) { return rng; } } // namespace range_detail using range_detail::moved_range; namespace adaptors { namespace { const range_detail::move_forwarder moved = {}; } // free functions template inline typename boost::disable_if< boost::is_lvalue_reference , moved_range > >::type move(Range&& rng) { return moved_range >(std::move(rng)); } template inline Range& move(Range& rng) { return rng; } #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST template inline moved_range, boost::fusion::vector<> > move(std::initializer_list il) { return moved_range, boost::fusion::vector<> >( std::move(il) ); } #endif } // namespace adaptors } // namespace boost #endif /**************************************** * Sample code for `moved` range adaptor * ****************************************/ #include #include #include #include template struct plus_ { typedef int result_type; int operator()(int val) const { return val + N; } }; struct my_array { int ar[3]; my_array() { ar[0] = 100, ar[1] = 200, ar[2] = 300; } ~my_array() { ar[0] = ar[1] = ar[2] = 0; } typedef int * iterator; typedef int const* const_iterator; iterator begin() { return ar; } const_iterator begin() const { return ar; } iterator end() { return ar + 3; } const_iterator end() const { return ar + 3; } }; int main (int argc, char* argv[]) { using namespace boost::adaptors; std::cout << "std::vector" << std::endl; for (int i : std::vector(3, 100) | moved | transformed(plus_<5>())) { std::cout << i << std::endl; } std::cout << std::endl; std::cout << "my_array" << std::endl; for (int i : my_array() | moved | reversed) { std::cout << i << std::endl; } std::cout << std::endl; #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST std::cout << "std::initializer_list" << std::endl; for (auto x : move( {1, 2, 3, 4, 5} ) | reversed | transformed(plus_<5>()) | reversed) { std::cout << x << std::endl; } std::cout << std::endl; #endif return 0; }