[Range] Adapt 2-iterator container constructors for Range?
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
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
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
Nat Goodspeed skrev:
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.
http://www.boost.org/doc/libs/1_36_0/libs/range/doc/utility_class.html#copy_... -Thorsten
Thorsten Ottosen wrote:
Nat Goodspeed skrev:
template
TYPE make_from_range(const RANGE& range);
http://www.boost.org/doc/libs/1_36_0/libs/range/doc/utility_class.html#copy_...
*blush* Thanks. I don't know why that didn't jump out at me when I looked through the documentation. Perhaps a brief usage example would have caught my attention more successfully. I'm still interested in the problem of declaring a local instance of a standard container without having to restate its type. I'd be happy with either Roman's approach or my own suggestion, but I do think the library would benefit from the addition of some such feature.
Nat Goodspeed skrev:
Thorsten Ottosen wrote:
Nat Goodspeed skrev:
template
TYPE make_from_range(const RANGE& range); http://www.boost.org/doc/libs/1_36_0/libs/range/doc/utility_class.html#copy_...
*blush* Thanks. I don't know why that didn't jump out at me when I looked through the documentation. Perhaps a brief usage example would have caught my attention more successfully.
I'm still interested in the problem of declaring a local instance of a standard container without having to restate its type. I'd be happy with either Roman's approach or my own suggestion, but I do think the library would benefit from the addition of some such feature.
I think that would be worthwhile. Romans suggestion seems elegant. Unfortunately, I don't have the time to implement/test/update the docs, (It takes some time before all these things are updated properly). but if you provide these as patches, and make a post on the dev list, I can manage to include it. If its possible to overload copy_range, I would prefer that. If you don't have the time, I'll put it on my todo list. best regards -Thorsten
participants (4)
-
Nat Goodspeed
-
Neal Becker
-
Roman Perepelitsa
-
Thorsten Ottosen