Boost Iterable Range Library update (v1.5)

Dear boosters, I have updated the Iterable Range Library (formely known as Range Templates Library). It makes dealing with containers/STL algorithms simpler by using ranges (as opposed to iterators). Simply put, a range is a smarter std::pair<iterator,iterator>. Here's a taste: for ( crange<some_array_type> r(some_array); r; ++r) do_something( *r, some_data); Also, the library provides wrappers for all STL algorithms (for the purpose of STL algorithms, all containers are ranges as well): typedef std::vector<std::string> word_array; word_array v; // STL version std::copy( v.begin(), v.end(), print); // rng:: version rng::copy( v, print); Also, the counterparts for STL algorithms that return an iterator will return a range, allowing for: // fill a vector with all the indexes at which a certain string is found std::string str = "I'm a cool programmer, really cool that is", find = "cool"; std::vector<int> result; crange<std::string> r(str); while ( r = rng::search(r, find)) result.push_back ( r.begin() - str.begin() ); And it provides for range adaptors, allowing for composition. bool from_ro(const employee & e) { return e.country == "Romania"; } std::string get_empl_name(const employee &e) { return e.name; } typedef std::vector<employee> array; array empls; // take all employees from Romania, and print their names rng::copy( transformed( filtered(empls,from_ro), get_empl_name), std::ostream_iterator<std::string>(std::cout," ")); Changes in this version: - improved algorithms.hpp (no more use of macros) - solved small bugs - added documentation Download it from here: http://www.torjo.com/rangelib/ Feedback is welcome. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

John Torjo wrote:
I have updated the Iterable Range Library (formely known as Range Templates Library).
No comments of the code itself, however I'm not a fan of rng as a namespace, I keep reading Random Number Generator. helpfully though I can't think of an alternative! range (likely to conflict?) irange (likely to be used as a variable name in place of 'i' ?) irl (not good either) rangelib (too long?) Kevin -- | Kevin Wheatley, Cinesite (Europe) Ltd | Nobody thinks this | | Senior Technology | My employer for certain | | And Network Systems Architect | Not even myself |

Kevin Wheatley <hxpro@cinesite.co.uk> writes:
John Torjo wrote:
I have updated the Iterable Range Library (formely known as Range Templates Library).
No comments of the code itself, however I'm not a fan of rng as a namespace, I keep reading Random Number Generator.
helpfully though I can't think of an alternative!
range (likely to conflict?) irange (likely to be used as a variable name in place of 'i' ?) irl (not good either) rangelib (too long?)
Tradition would dictate "ranges" -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

No comments of the code itself, however I'm not a fan of rng as a namespace, I keep reading Random Number Generator.
helpfully though I can't think of an alternative!
range (likely to conflict?) irange (likely to be used as a variable name in place of 'i' ?) irl (not good either) rangelib (too long?)
Tradition would dictate "ranges"
I'm fine with ranges:: namespace, although I find it a little big (containing too many chars). Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

John Torjo wrote:
No comments of the code itself, however I'm not a fan of rng as a namespace, I keep reading Random Number Generator. helpfully though I can't think of an alternative!
range (likely to conflict?) irange (likely to be used as a variable name in place of 'i' ?) irl (not good either) rangelib (too long?)
Tradition would dictate "ranges"
I'm fine with ranges:: namespace, although I find it a little big (containing too many chars).
I prefer descriptive names, and everyone is free to declare a namespace alias in his own code... namespace br = boost::ranges; Greetings, Roland
Best, John

At 08:10 AM 11/8/2004, John Torjo wrote:
No comments of the code itself, however I'm not a fan of rng as a namespace, I keep reading Random Number Generator.
helpfully though I can't think of an alternative!
range (likely to conflict?) irange (likely to be used as a variable name in place of 'i' ?) irl (not good either) rangelib (too long?)
Tradition would dictate "ranges"
I'm fine with ranges:: namespace, although I find it a little big (containing too many chars).
But it is way better than "rng", IMO. I'm like John, and read rng as random number generator. --Beman

John Torjo <john.lists@torjo.com> writes:
And it provides for range adaptors, allowing for composition.
bool from_ro(const employee & e) { return e.country == "Romania"; } std::string get_empl_name(const employee &e) { return e.name; }
typedef std::vector<employee> array; array empls;
// take all employees from Romania, and print their names rng::copy( transformed( filtered(empls,from_ro), get_empl_name), std::ostream_iterator<std::string>(std::cout," "));
Changes in this version: - improved algorithms.hpp (no more use of macros) - solved small bugs - added documentation
Download it from here: http://www.torjo.com/rangelib/
Have you thought about compatibility and integration with fusion? http://www.boost-consulting.com/boost/libs/spirit/fusion/readme.txt or libs/spirit/fusion/readme.txt in your Boost tree. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Have you thought about compatibility and integration with fusion?
http://www.boost-consulting.com/boost/libs/spirit/fusion/readme.txt
or
libs/spirit/fusion/readme.txt
in your Boost tree.
I have not yet considered this. I have just read the readme.txt, and it's still pretty fuzzy to me. I need a little more time to grasp the concept, to understand if ranges can fit here as well. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

"John Torjo" <john.lists@torjo.com> wrote in message news:418F4161.7050202@torjo.com... | Dear boosters, | | I have updated the Iterable Range Library (formely known as Range | Templates Library). First let me say that I think the library is ready for a review. (I think we need two people to say so by the new submission procedure). Some comments: 1. I prefer a more explicit version of a.. r.begin(new_begin) - resets the range's begin a.. r.end(new_end) - resets the range's end ie, I would like to see set_begin(...). // STL version std::transform( v1.begin(), v1.end(), v2.begin(), std::back_inserter(v3), std::max<int>); // rng:: version rng::transform( v1, v2, std::back_inserter(v3), std::max<int>); -------------------- initially an iterator would be enough in place of v2. So in some sense I think you should mention that you have make the requirement a bit stricter. 3. The docs for The i_ or i_param shortcut could be better. 4. "The coll_find is a shortcut for finding an element in a collection (non-associative array). ". The example then shows a map. Isn't a map an associative container? 5. some more docs on range adapters should be added. As a minimum requirement we need the synopsis of transformed() etc so we can see what it returns and takes. I some sense you have a very good toturial...now we need the reference docs. 6. from some of the sorce files, you seems to be using r.begin() instead of begin(r). 7. "to_end: return the [found, container.end()) range (this is the default" how do you implement defaults on function templates??? 8. have you thought about flags for error-strategies: find<or_throw>( v, 5 ); find( v, 5 ); find<to_end,or_throw>( v, 5 ); -Thorsten

Hi Thorsten,
First let me say that I think the library is ready for a review. (I think we
Thanks.
1.
I prefer a more explicit version of a.. r.begin(new_begin) - resets the range's begin a.. r.end(new_end) - resets the range's end ie, I would like to see set_begin(...).
yup, will do. I will certainly update the docs as soon as I have some more time.
// STL version std::transform( v1.begin(), v1.end(), v2.begin(), std::back_inserter(v3), std::max<int>);
// rng:: version rng::transform( v1, v2, std::back_inserter(v3), std::max<int>); --------------------
initially an iterator would be enough in place of v2. So in some sense I think you should mention that you have make the requirement a bit stricter.
probaly. Also, I mentioned the i_ parameter.
3. The docs for The i_ or i_param shortcut could be better.
yup
4. "The coll_find is a shortcut for finding an element in a collection (non-associative array). ". The example then shows a map. Isn't a map an associative container?
oh crap ;) That was my mistake in the docs. Will fix it. Thanks.
5. some more docs on range adapters should be added. As a minimum requirement we need the synopsis of transformed() etc so we can see what it returns and takes. I some sense you have a very good toturial...now we need the reference docs.
yes, definitely. Again, will do it as soon as I have the time..
6. from some of the sorce files, you seems to be using r.begin() instead of begin(r).
I need to thoroughly think about this.
7. "to_end: return the [found, container.end()) range (this is the default"
how do you implement defaults on function templates???
he he ;) Take a look at the implementation ;) (in this case, I did it with a typedef enum)
8. have you thought about flags for error-strategies:
find<or_throw>( v, 5 ); find( v, 5 ); find<to_end,or_throw>( v, 5 );
First of all, I think adding more than one template flags might be very hard to implement. Now, on the other side, if others are ok with this, I could certainly implement it. I donot see much value in the 'or_throw' strategy, since the same could be accomplished like this: if ( !find(v,5) ) throw "whatever"; What do others think? What other strategies are there? Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

"John Torjo" <john.lists@torjo.com> wrote in message news:419091AE.60903@torjo.com... | Hi Thorsten, | > 6. from some of the sorce files, you seems to be using r.begin() instead of | > begin(r). | | I need to thoroughly think about this. why? Don't you want to use boost.range as the infrastructure? | > 8. have you thought about flags for error-strategies: | > | > find<or_throw>( v, 5 ); | > find( v, 5 ); | > find<to_end,or_throw>( v, 5 ); | > | | First of all, I think adding more than one template flags might be very | hard to implement. | | Now, on the other side, if others are ok with this, I could certainly | implement it. I donot see much value in the 'or_throw' strategy, since | the same could be accomplished like this: | | if ( !find(v,5) ) throw "whatever"; | | What do others think? What other strategies are there? I guess the fact that it is now easy to check the return type as a boolean makes it easier. If we get back an iterator, we would have to do the clumsy != x.end(). -Thorsten

This is a subject in which I've had some interest. In my case this resulted in the "dataflow iterator" part of the serialization library. I've just looked at the documention referred to below rather than the code. Still, I have some questions: Its not clear to me what the benefit of using ranges is compared to a pair of iterators. "John Torjo" <john.lists@torjo.com> wrote in message news:418F4161.7050202@torjo.com...
It makes dealing with containers/STL algorithms simpler by using ranges (as opposed to iterators).
for ( crange<some_array_type> r(some_array); r; ++r) do_something( *r, some_data);
How is this simpler or more transparent than for(some_array::iterator i=some_array.begin(); i != some_array.end(); ++i) do_something( *i, some_data);
Also, the library provides wrappers for all STL algorithms (for the purpose of STL algorithms, all containers are ranges as well):
typedef std::vector<std::string> word_array; word_array v; // STL version std::copy( v.begin(), v.end(), print); // rng:: version rng::copy( v, print);
I don't see this as adding any value or conceptual transparency.
Also, the counterparts for STL algorithms that return an iterator will return a range, allowing for: // fill a vector with all the indexes at which a certain string is found std::string str = "I'm a cool programmer, really cool that is", find = "cool"; std::vector<int> result; crange<std::string> r(str); while ( r = rng::search(r, find)) result.push_back ( r.begin() - str.begin() );
I'm not really sure that I understand this example. It would seem the standard stl equivalent would be std::vector<int> result; std::string str = "I'm a cool programmer, really cool that is"; std::string find = "cool"; std::string::const_iterator r = str.begin(); while(r = stl::search(r, find.begin(), find.end())) result.push_back ( r.begin() - str.begin() ); which to my mind isn't any different or more complex.
And it provides for range adaptors, allowing for composition.
bool from_ro(const employee & e) { return e.country == "Romania"; } std::string get_empl_name(const employee &e) { return e.name; }
typedef std::vector<employee> array; array empls;
// take all employees from Romania, and print their names rng::copy( transformed( filtered(empls,from_ro), get_empl_name), std::ostream_iterator<std::string>(std::cout," "));
I don't see how this is better than using iterator adaptors for composition. The Dataflow Iterators part of the serialization library includes examples such as: typedef typedef insert_linebreaks< // insert line breaks every 72 characters base64_from_binary< // convert binary values ot base64 characters transform_width< // retrieve 6 bit integers from a sequence of 8 bit bytes const char *, 6, 8 > > ,72 > base64_text; // compose all the above operations in to a new iterator std::copy( base64_text(address), base64_text(address + count), ostream_iterator<CharType>(os) ); It would seem that ranges could only applied to forward iterators - excluding the usage of input iterators. It would also exclude transformations that don't create an intermediate temporary container. E.G. zip transform (similar to a unix paste command) which merges two iterator adaptors into one. Basically, this seems to me an extra layer that doesn't add any new concept or make things more transparent. I will concede that it might save a tiny bit of typing. I've used the Dataflow Iterators to contrast mainly because I wrote it and am familiar with it. I'm aware of a number of other similar efforts. When faced with this problem, I did consider development of the concept of ranges. After looking around and experimenting with it I concluded that the orginal STL used iterators rather than ranges for a reason - and a good one at that. Robert Ramey

Hi Robert,
This is a subject in which I've had some interest. In my case this resulted in the "dataflow iterator" part of the serialization library. I've just looked at the documention referred to below rather than the code. Still, I have some questions:
Its not clear to me what the benefit of using ranges is compared to a pair of iterators.
Manual loops: for ( crange<some_array_type> r(some_array); r; ++r) do_something( *r, some_data); Also, while coding, sometimes I have more complex loos, in which case I need to decrement r, etc.
It makes dealing with containers/STL algorithms simpler by using ranges (as opposed to iterators).
for ( crange<some_array_type> r(some_array); r; ++r) do_something( *r, some_data);
How is this simpler or more transparent than
for(some_array::iterator i=some_array.begin(); i != some_array.end(); ++i) do_something( *i, some_data);
more compact, and not error prone. Also, very useful in combination with algorithms that return ranges.
Also, the library provides wrappers for all STL algorithms (for the purpose of STL algorithms, all containers are ranges as well):
typedef std::vector<std::string> word_array; word_array v; // STL version std::copy( v.begin(), v.end(), print); // rng:: version rng::copy( v, print);
I don't see this as adding any value or conceptual transparency.
Not sure I understand what you mean.
Also, the counterparts for STL algorithms that return an iterator will return a range, allowing for: // fill a vector with all the indexes at which a certain string is found std::string str = "I'm a cool programmer, really cool that is", find = "cool"; std::vector<int> result; crange<std::string> r(str); while ( r = rng::search(r, find)) result.push_back ( r.begin() - str.begin() );
I'm not really sure that I understand this example. It would seem the standard stl equivalent would be
std::vector<int> result; std::string str = "I'm a cool programmer, really cool that is"; std::string find = "cool";
std::string::const_iterator r = str.begin(); while(r = stl::search(r, find.begin(), find.end())) result.push_back ( r.begin() - str.begin() );
which to my mind isn't any different or more complex.
in fact, you forgot to compare r to str.end()
// take all employees from Romania, and print their names rng::copy( transformed( filtered(empls,from_ro), get_empl_name), std::ostream_iterator<std::string>(std::cout," "));
I don't see how this is better than using iterator adaptors for composition.
Please, try the above with iterator adaptors, and show me the code. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

"John Torjo" <john.lists@torjo.com> wrote in message news:41909351.4030100@torjo.com... example 1
It makes dealing with containers/STL algorithms simpler by using ranges (as opposed to iterators).
for ( crange<some_array_type> r(some_array); r; ++r) do_something( *r, some_data);
How is this simpler or more transparent than
for(some_array::iterator i=some_array.begin(); i != some_array.end(); ++i) do_something( *i, some_data);
more compact, and not error prone.
I see only the smallest difference here.
Also, very useful in combination with algorithms that return ranges.
I'll address this below example 2
Also, the library provides wrappers for all STL algorithms (for the purpose of STL algorithms, all containers are ranges as well):
typedef std::vector<std::string> word_array; word_array v; // STL version std::copy( v.begin(), v.end(), print); // rng:: version rng::copy( v, print);
I don't see this as adding any value or conceptual transparency.
Not sure I understand what you mean.
This is really an extension of my observation above (marked example 1). My view is that the concept of ranges doesn't add enough to the concept of iterators to make it worth adding another layer to remember.
std::vector<int> result; std::string str = "I'm a cool programmer, really cool that is"; std::string find = "cool";
std::string::const_iterator r = str.begin(); while(r = stl::search(r, find.begin(), find.end())) result.push_back ( r.begin() - str.begin() );
which to my mind isn't any different or more complex.
in fact, you forgot to compare r to str.end()
correct while(str.end != (r = stl::search(r, find.begin(), find.end()))) again, I don't see that using ranges adds anything
// take all employees from Romania, and print their names rng::copy( transformed( filtered(empls,from_ro), get_empl_name), std::ostream_iterator<std::string>(std::cout," "));
I don't see how this is better than using iterator adaptors for composition.
Attached is the equivalent code using iterators. It includes code to add templeted constructors to iterators and to make functors for this particular example. Otherwise its very similar in functionality. And that is my point. I don't see that ranges are anything more than a very thin layer over iterators. Admitidly, iterators could perhaps use some embellishment (perhaps templated constructors) or other things to make them easier to use, but I don't think a whole now layer/view is warrented. I would prefer to see such efforts invested in making iterators easier to use without hidind their essential character. Robert Ramey begin 666 test_zmisc.cpp M(VEN8VQU9&4@/'9E8W1O<CX-"B-I;F-L=61E(#QS=')I;F<^#0HC:6YC;'5D M92 \86QG;W)I=&AM/@T*(VEN8VQU9&4@/&9U;F-T:6]N86P^#0HC:6YC;'5D M92 \:6]S=')E86T^#0HC:6YC;'5D92 \8F]O<W0O:71E<F%T;W(O9FEL=&5R M7VET97)A=&]R+FAP<#X-"B-I;F-L=61E(#QB;V]S="]I=&5R871O<B]T<F%N M<V9O<FU?:71E<F%T;W(N:'!P/@T*#0IS=')U8W0@96UP;&]Y964@>PT*(" @ M('-T9#HZ<W1R:6YG(&YA;64[#0H@(" @<W1D.CIS=')I;F<@8V]U;G1R>3L- M"GT[#0H-"F)O;VP@9G)O;5]R;RAC;VYS="!E;7!L;WEE92 F(&4I('L@<F5T M=7)N(&4N8V]U;G1R>2 ]/2 B4F]M86YI82([('T-"F-O;G-T('-T9#HZ<W1R M:6YG("8@9V5T7V5M<&Q?;F%M92AC;VYS="!E;7!L;WEE92 F92D@>R!R971U M<FX@92YN86UE.R!]#0H-"B\O(&%M96YD(&)Y('=A>2!O9B!D97)I=F%T:6]N M(&)O;W-T('1R86YS9F]R;2!A;F0@9FEL=&5R(&ET97)A=&]R<R -"B\O('1O M(&EN8VQU9&4@=&5M<&QA=&5D(&-O;G-T<G5C=&EO;BX@(%1H:7,@<V%V97,@ M;&]T<R!O9B!T>7!I;F<N#0HO+R!097)H87!S('-O;65D87D@=&5M<&QA=&5D M(&-O;G-T<G5C=&]R<R!M:6=H="!B92!A9&1E9"!T;R -"B\O(&ET97)A=&]R M(&%D87!T;W)S("T@=&AE<F5B>2!M86MI;F<@<W5C:"!A;65N9&UE;G1S('5N M;F5C97-S87)Y#0IN86UE<W!A8V4@86UE;F1E9"![#0H-"G1E;7!L871E(#P- M"B @("!C;&%S<R!5;F%R>49U;F-T:6]N+ T*(" @(&-L87-S($ET97)A=&]R M+" -"B @("!C;&%S<R!2969E<F5N8V4@/2!B;V]S=#HZ=7-E7V1E9F%U;'0L M( T*(" @(&-L87-S(%9A;'5E(#T@8F]O<W0Z.G5S95]D969A=6QT#0H^#0IC M;&%S<R!T<F%N<V9O<FU?:71E<F%T;W(@.B -"B @("!P=6)L:6,@8F]O<W0Z M.G1R86YS9F]R;5]I=&5R871O<CP-"B @(" @(" @56YA<GE&=6YC=&EO;BP- M"B @(" @(" @271E<F%T;W(L( T*(" @(" @("!2969E<F5N8V4L( T*(" @ M(" @("!686QU90T*(" @(#X-"GL-"G!U8FQI8SH-"B @("!T96UP;&%T93QC M;&%S<R!4/@T*(" @('1R86YS9F]R;5]I=&5R871O<BAC;VYS="!4("8@<W1A M<G0I(#H-"B @(" @(" @8F]O<W0Z.G1R86YS9F]R;5]I=&5R871O<CP-"B @ M(" @(" @(" @(%5N87)Y1G5N8W1I;VXL#0H@(" @(" @(" @("!)=&5R871O M<BP@#0H@(" @(" @(" @("!2969E<F5N8V4L( T*(" @(" @(" @(" @5F%L M=64-"B @(" @(" @/BA)=&5R871O<BAS=&%R="DL(%5N87)Y1G5N8W1I;VXH M*2D-"B @("![?0T*?3L-"@T*=&5M<&QA=&4@/&-L87-S(%!R961I8V%T92P@ M8VQA<W,@271E<F%T;W(^#0IC;&%S<R!F:6QT97)?:71E<F%T;W(@(#H-"B @ M("!P=6)L:6,@8F]O<W0Z.F9I;'1E<E]I=&5R871O<CP-"B @(" @(" @4')E M9&EC871E+ T*(" @(" @("!)=&5R871O<@T*(" @(#X-"GL-"G!U8FQI8SH- M"B @("!T96UP;&%T93QC;&%S<R!4/@T*(" @(&9I;'1E<E]I=&5R871O<BAC M;VYS="!4("8@<W1A<G0I(#H-"B @(" @(" @8F]O<W0Z.F9I;'1E<E]I=&5R M871O<CP-"B @(" @(" @(" @(%!R961I8V%T92P-"B @(" @(" @(" @($ET M97)A=&]R#0H@(" @(" @(#XH4')E9&EC871E*"DL($ET97)A=&]R*'-T87)T M*2D-"B @("![?0T*?3L-"@T*?2 O+R!N86UE<W!A8V4@86UE;F1E9 T*#0IS M=')U8W0@9V5T7V5M<&Q?;F%M95]F(#H@#0H@(" @<'5B;&EC('-T9#HZ=6YA M<GE?9G5N8W1I;VX\8V]N<W0@96UP;&]Y964@)BP@8V]N<W0@<W1D.CIS=')I M;F<@)CX-"GL-"B @("!C;VYS="!S=&0Z.G-T<FEN9R F(&]P97)A=&]R*"DH M8V]N<W0@96UP;&]Y964@)F4I(&-O;G-T('L-"B @(" @(" @<F5T=7)N(&=E M=%]E;7!L7VYA;64H92D[#0H@(" @?0T*?3L-"@T*<W1R=6-T(&9R;VU?<F]? M9B Z#0H@(" @<'5B;&EC('-T9#HZ=6YA<GE?9G5N8W1I;VX\8V]N<W0@96UP M;&]Y964@)BP@8V]N<W0@<W1D.CIS=')I;F<@)CX-"GL-"B @("!B;V]L(&]P M97)A=&]R*"DH8V]N<W0@96UP;&]Y964@)F4I(&-O;G-T('L-"B @(" @(" @ M<F5T=7)N(&9R;VU?<F\H92D[#0H@(" @?0T*?3L-"@T*#0II;G0@;6%I;B@I M>PT*(" @('1Y<&5D968@<W1D.CIV96-T;W(\96UP;&]Y964^(&%R<F%Y.PT* M(" @(&%R<F%Y(&5M<&QS.PT*(" @( T*(" @('1Y<&5D968@86UE;F1E9#HZ M=')A;G-F;W)M7VET97)A=&]R/ T*(" @(" @("!G971?96UP;%]N86UE7V8L M#0H@(" @(" @(&%M96YD960Z.F9I;'1E<E]I=&5R871O<CP-"B @(" @(" @ M(" @(&9R;VU?<F]?9BP-"B @(" @(" @(" @('-T9#HZ=F5C=&]R/&5M<&QO M>65E/CHZ8V]N<W1?:71E<F%T;W(-"B @(" @(" @/@T*(" @(#X@<F]M86YI M86Y?;F%M97-?=#L-"B @(" @( T*(" @('-T9#HZ8V]P>2@-"B @(" @(" @ M<F]M86YI86Y?;F%M97-?="AE;7!L<RYB96=I;B@I*2P-"B @(" @(" @<F]M M86YI86Y?;F%M97-?="AE;7!L<RYE;F0H*2DL#0H@(" @(" @('-T9#HZ;W-T M<F5A;5]I=&5R871O<CQS=&0Z.G-T<FEN9SXH<W1D.CIC;W5T+"(@(BD-"B @ M(" I.R @( T*?0T*(" @("\O('1A:V4@86QL(&5M<&QO>65E<R!F<F]M(%)O M;6%N:6$L(&%N9"!P<FEN="!T:&5I<B!N86UE<PT*+R\@(" @<W1D.CIC;W!Y M*"!T<F%N<V9O<FUE9"@@9FEL=&5R960H96UP;',L9G)O;5]R;RDL(&=E=%]E M;7!L7VYA;64I+ T*+R\@(" @(" @('-T9#HZ;W-T<F5A;5]I=&5R871O<CQS @=&0Z.G-T<FEN9SXH<W1D.CIC;W5T+"(@(BDI.PT*#0H` ` end

"Robert Ramey" <ramey@rrsd.com> wrote in message news:cmrbom$qcv$1@sea.gmane.org... | | "John Torjo" <john.lists@torjo.com> wrote in message | news:41909351.4030100@torjo.com... | | example 1 | | > >>It makes dealing with containers/STL algorithms simpler by using ranges | > >>(as opposed to iterators). | Attached is the equivalent code using iterators. | | It includes code to add templeted constructors to iterators and to make | functors for this particular example. Otherwise its very similar in | functionality. And that is my point. I don't see that ranges are anything | more than a very thin layer over iterators. Admitidly, iterators could | perhaps use some embellishment (perhaps templated constructors) or other | things to make them easier to use, but I don't think a whole now layer/view | is warrented. I would prefer to see such efforts invested in making | iterators easier to use without hidind their essential character. If you are going to convince me iterators are easy to use, you have to come up with something better than typedef amended::transform_iterator< get_empl_name_f, amended::filter_iterator< from_ro_f, std::vector<employee>::const_iterator > > romanian_names_t; std::copy( romanian_names_t(empls.begin()), romanian_names_t(empls.end()), std::ostream_iterator<std::string>(std::cout," ") ); Seriously, this is so ugly and hard to write that I predict less than 1% of the community will ever use it. -Thorsten

Hmmm - now this is very interesting to me. To me, the syntax below is very obvious and transparent - even elegant. In fact, its the feature I like most about the whole proposal. It lets me compose iterators at compile time with mininal runtime cost. It also permits composition at compile time in what I see is a natural manner typedef amended::filter_iterator< from_ro_f, std::vector<employee>::const_iterator
romainians_t;
typedef amended::transform_iterator< get_empl_name_f, romainians_t
romanian_names_t;
In the serialization library it permitted me to make a set of "relatively" simple single purpose iterators like mb_from_wchar, remove_spaces, transform_width<8,6> etc and compose them in various ways to make things like from_base64, xml_escape, etc. In some cases, the input end wasn't so easy to handle. This included trnaslation from 8 bit octets to 6 bit ?, input from input iterators. I did consider the idea of ranges but didn't see it working for me here. - I don't remember the details. The extreme rigor and formality of the new boost itertator was both a curse and a blessing. Making the "dataflow" iterators seemingly harder to make. But all the compositions (some fairly deep) worked as expected with no debugging. I'm extremely interested in seeing this idea explored more in the future. "Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cmrgnj$6lu$1@sea.gmane.org...
If you are going to convince me iterators are easy to use, you have to come up with something better than
typedef amended::transform_iterator< get_empl_name_f, amended::filter_iterator< from_ro_f, std::vector<employee>::const_iterator > > romanian_names_t;
std::copy( romanian_names_t(empls.begin()), romanian_names_t(empls.end()), std::ostream_iterator<std::string>(std::cout," ") );
note: I'm presuming that you have no problem with std::copy ... syntax here
Seriously, this is so ugly and hard to write that I predict less than 1% of the community will ever use it.
LOL- I think just the opposite. I guess its in the eye of the beholder. The funnest part of this is that I specifically crafted the code to permit exactly this syntax. I'm amazed there there exists even one person that has a negative reaction to it. Its immensly intriguing to me that we can have exact opposite reactions to this. I'll be curious to hear what others think. Robert Ramey

"Robert Ramey" <ramey@rrsd.com> wrote in message news:cmrj00$ck1$1@sea.gmane.org... | see it working for me here. - I don't remember the details. The extreme | rigor and formality of the new boost itertator was both a curse and a | blessing. Making the "dataflow" iterators seemingly harder to make. But | all the compositions (some fairly deep) worked as expected with no | debugging. I'm extremely interested in seeing this idea explored more in | the future. | | "Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message | news:cmrgnj$6lu$1@sea.gmane.org... | | > If you are going to convince me iterators are easy to use, you have to | come up | > with something better than | > Seriously, this is so ugly and hard to write that I predict less than 1% | of | > the community will ever use it. | | LOL- I think just the opposite. I guess its in the eye of the beholder. | The funnest part of this is that I specifically crafted the code to permit | exactly this syntax. I'm amazed there there exists even one person that has | a negative reaction to it. Its immensly intriguing to me that we can have | exact opposite reactions to this. I'll be curious to hear what others | think. Here's my general take on it: iterators are important and useful as the lower-level infrastructure. iterators are, however, not too user-friendly; the user-friendly interface can be build on top so easy task becomes , well, easy. and that is the purpose of ranges and johns range library. without a good iterator library underneith ranges where hard to craft, but now that we have a good iterator library, we should persue higher abstractions -Thorsten

Here's my general take on it: iterators are important and useful as the lower-level infrastructure. iterators are, however, not too user-friendly; the user-friendly interface can be build on top so easy task becomes , well, easy. and that is the
"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cmrk1g$f70$1@sea.gmane.org... purpose
of ranges and johns range library. without a good iterator library underneith ranges where hard to craft, but now that we have a good iterator library, we should persue higher abstractions
I agree that iterators aren't that easy or intuitive to work with. So our motivations have much in common. My view is that iterators can be made easier to work with without changing their fundamental character and without the need to introduce what I see as a new concept (ranges) that is "almost the same" as an existing concept - pair of iterators. Robert Ramey

From: "Robert Ramey" <ramey@rrsd.com> | I agree that iterators aren't that easy or intuitive to work with. So our | motivations have much in common. My view is that iterators can be made | easier to work with without changing their fundamental character and without | the need to introduce what I see as a new concept (ranges) that is "almost | the same" as an existing concept - pair of iterators. ยด pair<iterator,iterator> is supported by the range library, so you can still use it if you want. -Thorsten

If you are going to convince me iterators are easy to use, you have to
come up
with something better than
typedef amended::transform_iterator< get_empl_name_f, amended::filter_iterator< from_ro_f, std::vector<employee>::const_iterator >
romanian_names_t;
std::copy( romanian_names_t(empls.begin()), romanian_names_t(empls.end()), std::ostream_iterator<std::string>(std::cout," ") );
The problem with iterators, even in Robert's example, is that to further compose them, you need to create wrapper functors (get_empl_name_f, from_ro_f). Again, as I've said in the docs, anything that can be done with function adaptors can be done with iterators. But the results will be more error-prone, harder to write and read. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

On 11/09/2004 03:10 PM, Robert Ramey wrote: [snip]
How is this simpler or more transparent than
for(some_array::iterator i=some_array.begin(); i != some_array.end();
++i) [snip]
I see only the smallest difference here.
Yes, as far as this example shows. I haven't look at other examples; however, I've coded this range idea myself just using something derived from pair<iterator,iterator>. There's was something already in boost that had ranges; however, I couldn't use it for some reason. I've also seen ranges coded elsewhere (in the polaris compiler at uiuc). If it's occurring so often, maybe it's worth having a library. Also, could someone tell me the reason for having, I believe Thorsten's, range library as well as this one? I've found the Thorsten's hard to use because it doesn't have a dereference function or advance function. How can these operations be done on ranges in that library?

"Larry Evans" <cppljevans@cox-internet.com> wrote in message news:cmrei9$229$1@sea.gmane.org... | On 11/09/2004 03:10 PM, Robert Ramey wrote: | [snip] | >>>How is this simpler or more transparent than | >>> | >>>for(some_array::iterator i=some_array.begin(); i != some_array.end(); | > | > ++i) | [snip] | > | > | > I see only the smallest difference here. | | Yes, as far as this example shows. I haven't look at other examples; | however, I've coded this range idea myself just using something | derived from pair<iterator,iterator>. There's was something | already in boost that had ranges; however, I couldn't use it for | some reason. I've also seen ranges coded elsewhere (in the polaris | compiler at uiuc). If it's occurring so often, maybe it's worth | having a library. | | Also, could someone tell me the reason for having, I believe | Thorsten's, range library as well as this one? John goes somewhat further and provides algorithms too. I do hope it can be part of boost.range. | I've found | the Thorsten's hard to use because it doesn't have a dereference | function or advance function. How can these operations be done | on ranges in that library? John goes one step further: he makes the ranges iterable, boost.range's ranges are not. I have focused on the core infrastructure used to define algorithms interfaces. If you want to use them easier using John' stuff, you can do so: crange< sub_range<string> > r = ....; I admit that is not elegant. I do believe crange<string> r2 = make_sub_range( r.begin(), r.end() ); should work. I guess the next version could be made iterable if people want. In that sense sub_range<> would replace crange<> in John's library. maybe John wouldn't mind? -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cmrhjn$92n$1@sea.gmane.org...
I guess the next version could be made iterable if people want. In that sense sub_range<> would replace crange<> in John's library. maybe John wouldn't mind?
I've already started using Boost.Range and find it very useful. John's examples look very interesting, too, although I haven't read his docs yet. I would definitely like to see the libraries integrated -- if that is possible -- rather than having another pair of partially overlapping libraries. Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:cmrije$bkh$1@sea.gmane.org... | | "Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message | news:cmrhjn$92n$1@sea.gmane.org... | | > | > I guess the next version could be made iterable if people want. In that sense | > sub_range<> would replace crange<> in John's library. maybe John wouldn't | > mind? | > | | I've already started using Boost.Range and find it very useful. John's examples | look very interesting, too, although I haven't read his docs yet. I would | definitely like to see the libraries integrated -- if that is possible -- rather | than having another pair of partially overlapping libraries. As far as I can see there is only a very small overlap...sub_range<> vs crange<> and iterator_range<> vs irange<>. So it should be possible. -Thorsten.

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cmrj3j$cu4$1@sea.gmane.org...
| I've already started using Boost.Range and find it very useful. John's examples | look very interesting, too, although I haven't read his docs yet. I would | definitely like to see the libraries integrated -- if that is possible -- rather | than having another pair of partially overlapping libraries.
As far as I can see there is only a very small overlap...sub_range<> vs crange<> and iterator_range<> vs irange<>. So it should be possible.
Good. I guess I'll understand this as soon as I read the documentation. ;-)
-Thorsten.
Jonathan

| | I've already started using Boost.Range and find it very useful. John's examples | look very interesting, too, although I haven't read his docs yet. I would | definitely like to see the libraries integrated -- if that is possible -- rather | than having another pair of partially overlapping libraries.
As far as I can see there is only a very small overlap...sub_range<> vs crange<> and iterator_range<> vs irange<>. So it should be possible.
I'm all for blending them together. Will work with Thorsten on this. The only problem for me is time - I see this happening probably in mid December or mid January. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

In algo.hpp, I see the following code: // template<class fwd_it, class out_it> out_it // rotate_copy(fwd_it first, fwd_it middle, fwd_it last, out_it result); template<class r, class fwd_it, class out_it> inline out_it rotate_coy(const r& val1, fwd_it val2, out_it val3) { return ::std::rotate_coy( val1.begin(), val1.end(), val2, val3 ); } template<class r, class fwd_it, class out_it> inline out_it rotate_coy(r& val1, fwd_it val2, out_it val3) { return ::std::rotate_coy( val1.begin(), val1.end(), val2, val3 ); } I would expect the range version of rotate_copy to take as first parameter a range, and as second parameter an iterator pointing to an element inside that range. The iterator version takes its iterators as first, middle, last. I think it is more intuitively to see [first, last) as the range, where middle is pointing into, instead of seeing [first, middle) as a range, augmented by a last iterator. You'd probably want to call this function as rotate_copy(container, container.begin() + 5, ...). With the current version, the first parameter probably always has to be crafted by hand, like rotate_copy(crange<container_type>(container.begin(), container.begin() + 5), container.end(), ...). best regards, Richard Peters

Richard Peters wrote:
In algo.hpp, I see the following code:
// template<class fwd_it, class out_it> out_it // rotate_copy(fwd_it first, fwd_it middle, fwd_it last, out_it result); template<class r, class fwd_it, class out_it> inline out_it rotate_coy(const r& val1, fwd_it val2, out_it val3) { return ::std::rotate_coy( val1.begin(), val1.end(), val2, val3 ); } template<class r, class fwd_it, class out_it> inline out_it rotate_coy(r& val1, fwd_it val2, out_it val3) { return ::std::rotate_coy( val1.begin(), val1.end(), val2, val3 ); }
also - I made a typo there (rotate_coy instead of rotate_copy)
I would expect the range version of rotate_copy to take as first parameter a range, and as second parameter an iterator pointing to an element inside
You are right. It was my mistake. Fixed it now, thanks. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html
participants (10)
-
Beman Dawes
-
David Abrahams
-
John Torjo
-
Jonathan Turkanis
-
Kevin Wheatley
-
Larry Evans
-
Richard Peters
-
Robert Ramey
-
Roland Weiss
-
Thorsten Ottosen