2008/9/24 Nat Goodspeed <nat@lindenlab.com>
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<class TYPE, typename RANGE>
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::vector<std::string> >
   my_vector(function_returning_range_of_string());

Why not
  vector<string> my_vector(make_from_range<vector<string> >(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<string*> 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.