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<string> 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