Boost logo

Boost Users :

Subject: Re: [Boost-users] [Range] Adapt 2-iterator container constructors for Range?
From: Neal Becker (ndbecker2_at_[hidden])
Date: 2008-09-24 10:23:09


Roman Perepelitsa wrote:

> 2008/9/24 Nat Goodspeed <nat_at_[hidden]>
>
>> 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.
I've been using this for years:
#ifndef const_from_range_hpp
#define const_from_range_hpp

#include <boost/range.hpp>
#include <algorithm>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/multi_array.hpp>

namespace detail {
  template<typename cont_t, typename range>
  struct construct_from_range_impl {
    cont_t operator() (range const& r) {
      return cont_t (boost::begin (r), boost::end (r));
    }
  };

  template<typename T, typename range>
  struct construct_from_range_impl<boost::numeric::ublas::vector<T>, range> {
    typedef typename boost::numeric::ublas::vector<T> ret_t;
    ret_t operator() (range const& r) {
      ret_t v (boost::size (r));
      std::copy (boost::begin (r), boost::end (r), v.begin());
      return v;
    }
  };

  template<typename T, typename range>
  struct construct_from_range_impl<boost::multi_array<T,1>, range> {
    typedef typename boost::multi_array<T,1> ret_t;
    ret_t operator() (range const& r) {
      ret_t v (r);
      return v;
    }
  };
}

template<typename cont_t, typename range>
cont_t inline construct_from_range (range const& r) {
  return detail::construct_from_range_impl<cont_t,range>() (r);
}

#endif


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net