Roman Perepelitsa wrote:
2008/9/24 Nat Goodspeed
As I work with Boost.Range, I frequently want to call a method returning an iterator_range and, from that range, instantiate a standard container. I have a couple of helpers I'd like to propose for inclusion in the Boost.Range library.
/** * From any range compatible with Boost.Range, return an instance of any * class with a constructor accepting a compatible iterator pair. */ template
TYPE make_from_range(const RANGE& range) { return TYPE(boost::begin(range), boost::end(range)); } It would probably be appropriate to provide a non-const RANGE& overload as well.
make_from_range<CONTAINER>(range) is helpful for, e.g., passing an argument to a function accepting const CONTAINER&. But what if you want to declare a local instance of such a container?
/** * From any range compatible with Boost.Range, instantiate any class * with a constructor accepting a compatible iterator pair. */ template<class TYPE> struct instance_from_range: public TYPE { template<typename RANGE> instance_from_range(const RANGE& range): TYPE(boost::begin(range), boost::end(range)) {} // Again, a non-const RANGE& overload would probably be useful. };
Usage example:
instance_from_range< std::vectorstd::string > my_vector(function_returning_range_of_string());
Why not vector<string> my_vector(make_from_range
(get_range()); ? RVO will make sure that no copies of a container are created. If you don't want to specify vector<string> twice you can follow the approach of Boost.Assign -- create an object with a conversion to anything and let it be converted to a container.
template <class Range> struct from_range_impl { from_range_impl(const Range& range) : range_(range) {} template <class Container> operator Container() const { return Container(begin(range_), end(range_)); } private: const Range& range_; };
template <class Range> from_range_impl<Range> make_from_range(const Range& range) { return from_range_impl<Range>(range); }
Example: void foo(const vector<string>& v);
iterator_range
range; foo(make_from_range(get_range(range)); vector<string> v(make_from_range(range)); Sometimes you'll still want to explicitly specify type of the container that should be created by make_from_range (for example when you pass it to an overloaded function), but you can keep both versions of make_from_range and use each of them when appropriate.
Roman Perepelitsa. I've been using this for years: #ifndef const_from_range_hpp #define const_from_range_hpp
#include