
I use this: template <typename Range> struct RangeWrapper { const Range& r; template <typename Container> operator Container() const { return Container(begin(r), end(r)); } }; template <typename Range> RangeWrapper<Range> range_to_container(const Range& r) { return RangeWrapper<Range>{r}; } Simple but effective. Regards, Nate. ----------------------------------------
Date: Tue, 7 Jun 2011 10:31:29 +0800 From: qiaozhiqiang@leadcoretech.com To: boost-users@lists.boost.org CC: mpbecey7gu@snkmail.com Subject: Re: [Boost-users] Ranges to Collections
Maybe you want make_vector() , make_list().
#include #include #include #include
#include // for test
template T make_container(const SinglePassRange& from) { T c; boost::push_back(c, from); return move(c); }
template std::vector make_vector(const SinglePassRange& from) { return make_container>(from); }
template std::list make_list(const SinglePassRange& from) { return make_container>(from); }
int main(int argc, _TCHAR* argv[]) { std::vector vector1; vector1.push_back(1); vector1.push_back(2); vector1.push_back(3);
std::list list1; list1.push_back(1); list1.push_back(2); list1.push_back(3);
auto vector2 = make_container>(vector1 | boost::adaptors::reversed); auto vector3 = make_vector(vector1 | boost::adaptors::reversed); auto vector4 = make_vector(vector1);
auto list2 = make_container>(list1 | boost::adaptors::reversed); auto list3 = make_list(list1 | boost::adaptors::reversed); auto list4 = make_list(list1);
return 0; }
------------------------------
Message: 2 Date: Mon, 06 Jun 2011 11:00:29 -0500 From: "John M. Dlugosz" To: boost-users@lists.boost.org Subject: [Boost-users] Ranges to Collections Message-ID: <15775-1307376032-823667@sneakemail.com> Content-Type: text/plain; charset=UTF-8; format=flowed
I like "ranges". When I first read the introduction to the ideas that would become STL, I did not like the use of begin/end iterators. Primarily, there is a possibility of getting them mixed up and the proposed library was explicitly not robust in the face of being passed bad parameters, such as not belonging to the same collection or not having the end after the begin. This was in direct contrast to the code I was promoting, which stressed API design that prevented errors from being possible, and strongly checking for everything else. The fact that they are not "functional" was harder to grasp exactly at the time, but it bothered me "in my gut".
When I read about the Boost Range library and the C++0x adoption of the range concept, I felt this to be a long sought improvement and would dramatically improve my use of STL.
Suffice to say, I'm a fan of Ranges. In new work, and in refactoring and improving code, I expect ranges to be one of the pillars of improvement. I'm sad to see that the draft standard dropped most of the range stuff (presumably it needs Concepts) but left in the intrinsic for-each loop. Anyway, the concrete compiler I have to work with, Visual Studio 2010, doesn't include it. So Boost.Range to the rescue! Except... the standard containers like vector don't have constructors that take ranges.
Consider something like: vector retval (rangefunc | rangefilter);
It really gets in the way to introduce a temporary variable of "some range type", but I see that the 'auto' feature comes to the rescue. I'm not used to having that available, so perhaps I'm over reacting.
But, is there a way to bridge the gap?
I take it patching the STL headers to add the missing constructors is frowned upon. But some syntactic sugar might get pretty close to that. First of all, what are people doing now? Maybe this has all be gone over before?
I can see creating a derived class from each STL container. The sole purpose of that class is to have the range constructor, and then the resulting instance is used as the base class, passed somewhere or copied. So you might write, for the previous example: range_vector retval (rangefunc | rangefilter);
and other code won't care about your derived class since it only existed district from the base class in order to add a constructor. In fact, a template might systematically do this to any class that has a constructor that takes two iterators: rangeit> retval (rangefunc | rangefilter);
This is less than desirable in cases where you were not going to state the type. Say, a return statement or parameter, where you would ideally have an implicit conversion from a range to the collection: return (rangefunc | rangefilter); // give a "range" where collection is expected
Could a helper template be written that has a simple name and doesn't need to be told the types involved? return range_to_collection (rangefunc | rangefilter);
Perhaps this produces a temporary object that supports a templatized conversion operator, so it can continue when that is told the type desired. I can see a few approaches, depending on what the compiler would swallow. But, has anyone already done this?
?John
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users