[boost.range] late addition, votes needed

Dear All, In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes: const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin(); The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea. Given the framework in boost.range these would be absolutely *trivial* to add. 1st vote: for or against adding these? 2nd vote: which naming scheme to use: a: cbegin(), cr_begin() b: const_begin(); const_rbegin(); The motivation for chosing the latter could be that "cr" contracttions become harder to read. Let me know what ya think. best regards Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
Dear All,
In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes:
const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin();
The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea.
Given the framework in boost.range these would be absolutely *trivial* to add.
1st vote: for or against adding these?
2nd vote: which naming scheme to use:
a: cbegin(), cr_begin()
b: const_begin(); const_rbegin();
The motivation for chosing the latter could be that "cr" contracttions become harder to read.
Let me know what ya think.
I wonder whether it's better to say cbegin(x) or begin(as_const(x)) The latter is certainly more general. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6uvle5e.fsf@boost-consulting.com...
"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
Dear All,
In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes:
const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin();
The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea.
Given the framework in boost.range these would be absolutely *trivial* to add.
1st vote: for or against adding these?
2nd vote: which naming scheme to use:
a: cbegin(), cr_begin()
b: const_begin(); const_rbegin();
The motivation for chosing the latter could be that "cr" contracttions become harder to read.
Let me know what ya think.
I wonder whether it's better to say
cbegin(x)
or
begin(as_const(x))
The latter is certainly more general.
Does this imply that the following would be possible: begin( as_reverse(x) ) begin( as_const( as_reverse(x) ) ) begin( as_reverse( as_const(x) ) ) Jeff F

"Jeff Flinn" <TriumphSprint2000@hotmail.com> wrote in message news:ci9qjr$ogt$1@sea.gmane.org... | | "David Abrahams" <dave@boost-consulting.com> wrote in message | news:uk6uvle5e.fsf@boost-consulting.com... | > "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > I wonder whether it's better to say | > | > cbegin(x) | > | > or | > | > begin(as_const(x)) | > | > The latter is certainly more general. | | Does this imply that the following would be possible: | | begin( as_reverse(x) ) rbegin(x) is alreeady there as a parallel to x.rbegin(). | begin( as_const( as_reverse(x) ) ) | begin( as_reverse( as_const(x) ) ) yes, I think so with some metaprgramming, but its getting quite hard to read compared to the single version. br Thorsten

From: "Thorsten Ottosen" <nesotto@cs.auc.dk>
"Jeff Flinn" <TriumphSprint2000@hotmail.com> wrote in message
| begin( as_const( as_reverse(x) ) ) | begin( as_reverse( as_const(x) ) )
yes, I think so with some metaprgramming, but its getting quite hard to read compared to the single version.
Those are getting harder to read, but they do offer complete generality. Composing those is straightforward, whereas you could forget the correct order if there was only as_const_reverse(), for example. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" <stewart@sig.com> wrote in message news:200409152006.i8FK6Bl06722@lawrencewelk.systems.susq.com... | From: "Thorsten Ottosen" <nesotto@cs.auc.dk> | > "Jeff Flinn" <TriumphSprint2000@hotmail.com> wrote in message | > | > | begin( as_const( as_reverse(x) ) ) | > | begin( as_reverse( as_const(x) ) ) | > | > yes, I think so with some metaprgramming, but its getting quite hard to read | > compared to the single version. | | Those are getting harder to read, but they do offer complete | generality. Composing those is straightforward, whereas you | could forget the correct order if there was only | as_const_reverse(), for example. yeah, but they are conceptually somewhat different: as_const() adds constness which works all over the plaec whereas as_reverse() only works for certain iterators; we already have rbegin(a) and so it seems that only as_const() would be needed. If so, its not a part of boost.range but boost.util br Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"Jeff Flinn" <TriumphSprint2000@hotmail.com> wrote in message news:ci9qjr$ogt$1@sea.gmane.org... | | "David Abrahams" <dave@boost-consulting.com> wrote in message | news:uk6uvle5e.fsf@boost-consulting.com... | > "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > I wonder whether it's better to say | > | > cbegin(x) | > | > or | > | > begin(as_const(x)) | > | > The latter is certainly more general. | | Does this imply that the following would be possible: | | begin( as_reverse(x) )
rbegin(x) is alreeady there as a parallel to x.rbegin().
| begin( as_const( as_reverse(x) ) ) | begin( as_reverse( as_const(x) ) )
yes, I think so with some metaprgramming, but its getting quite hard to read compared to the single version.
No fancy metaprogramming is required. This is simple stuff. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

1st vote: for or against adding these?
For.
Does this imply that the following would be possible:
begin( as_reverse(x) ) begin( as_const( as_reverse(x) ) ) begin( as_reverse( as_const(x) ) )
I'm also in favor of this. Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4.0 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)

"Jeff Flinn" <TriumphSprint2000@hotmail.com> writes:
Does this imply that the following would be possible:
begin( as_reverse(x) )
Well, you could create a reversed container adaptor I guess. My first thought was that make_reverse_iterator(begin(x)) was the right incantation. But I might like your idea better.
begin( as_const( as_reverse(x) ) ) begin( as_reverse( as_const(x) ) )
Yes, I'm quite fond of those. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

[Note: this is a reply to Thorsten's post, which hasn't shown up on my newsreader yet. I've been missing a lot ot messages lately -- is this happening to anyone else?]
"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
Dear All,
In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes:
const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin();
The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea.
Given the framework in boost.range these would be absolutely *trivial* to add.
1st vote: for or against adding these?
2nd vote: which naming scheme to use:
a: cbegin(), cr_begin()
b: const_begin(); const_rbegin();
The motivation for chosing the latter could be that "cr" contracttions become harder to read.
Let me know what ya think.
I faced this problem with the memory-mapped file implementation in iostreams, since whether the underlying file is open in read-only mode has absolutely nothing to do with whether the mapped_file object is const. I chose 'const_begin' and 'const_end' because these names - sound very natural to me - are not too verbose - make the sematics obvious. Best Regards, Jonathan

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6uvle5e.fsf@boost-consulting.com...
"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes:
const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin();
The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea.
Given the framework in boost.range these would be absolutely *trivial* to add.
1st vote: for or against adding these?
2nd vote: which naming scheme to use:
a: cbegin(), cr_begin()
b: const_begin(); const_rbegin();
The motivation for chosing the latter could be that "cr" contracttions become harder to read.
Let me know what ya think.
I wonder whether it's better to say
cbegin(x)
or
begin(as_const(x))
The latter is certainly more general.
Would this imply also: begin(as_reverse(x)) begin(as_reverse(as_const(x))) begin(as_const(as_reverse(x))) Jeff F

On Sep 15, 2004, at 10:09 AM, Thorsten Ottosen wrote:
Dear All,
In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes:
const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin();
The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea.
Given the framework in boost.range these would be absolutely *trivial* to add.
1st vote: for or against adding these?
Against. If the C++ committee likes them, we can add them into a later revision of Boost. Doug

"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message news:DD33A4E0-0733-11D9-8C97-000A95B0EC64@cs.indiana.edu... | | On Sep 15, 2004, at 10:09 AM, Thorsten Ottosen wrote: | > Given the framework in boost.range these would be absolutely *trivial* | > to add. | > | > 1st vote: for or against adding these? | | Against. If the C++ committee likes them, we can add them into a later | revision of Boost. Ok, but doesn't it usually work the way that things go into boost first? If not for anything else, then to see if the stuff works in practice? br Thorsten

On Sep 15, 2004, at 1:09 PM, Thorsten Ottosen wrote:
"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message news:DD33A4E0-0733-11D9-8C97-000A95B0EC64@cs.indiana.edu... | | On Sep 15, 2004, at 10:09 AM, Thorsten Ottosen wrote:
| > Given the framework in boost.range these would be absolutely *trivial* | > to add. | > | > 1st vote: for or against adding these? | | Against. If the C++ committee likes them, we can add them into a later | revision of Boost.
Ok, but doesn't it usually work the way that things go into boost first? If not for anything else, then to see if the stuff works in practice?
cbegin()/cend() aren't all that useful unless they also work with the standard library containers. If it's never going to happen for the standard containers, why bother putting it into Boost? Something like "as_const(c)" is a totally different story, of course. Doug

"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message news:FA3C64CC-0745-11D9-8C97-000A95B0EC64@cs.indiana.edu... | | On Sep 15, 2004, at 1:09 PM, Thorsten Ottosen wrote: | > Ok, but doesn't it usually work the way that things go into boost | > first? If | > not for anything else, then to | > see if the stuff works in practice? | | cbegin()/cend() aren't all that useful unless they also work with the | standard library containers. all code in boost.range works with standard containers. the frame only require begin/end functions (not even rbegin/rend) to be present in the container. br Thorsten

"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message:
cbegin()/cend() aren't all that useful unless they also work with the standard library containers. If it's never going to happen for the standard containers, why bother putting it into Boost? Something like "as_const(c)" is a totally different story, of course.
Why can't const_begin be implemented as follows (for standard library containers): template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); } template<typename Range> typename range_const_iterator<X>::type const_begin(const Range& rng) { return begin(rng); } ? Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:cia4al$nfe$1@sea.gmane.org... | | "Doug Gregor" <dgregor@cs.indiana.edu> wrote in message: | | > | > cbegin()/cend() aren't all that useful unless they also work with the | > standard library containers. If it's never going to happen for the | > standard containers, why bother putting it into Boost? Something like | > "as_const(c)" is a totally different story, of course. | | Why can't const_begin be implemented as follows (for standard library | containers): well, it can...otherwise I wouldn't have made the post. It's similar to rbegin(a) in the sense that it only require a.begin() | template<typename Range> | typename range_const_iterator<X>::type | const_begin(Range& rng) | { | return begin(static_cast<const Range&>(rng)); | } this should not be needed, the next is sufficient | template<typename Range> | typename range_const_iterator<X>::type X == Range | const_begin(const Range& rng) | { | return begin(rng); | } | br Thorsten

"Jonathan Turkanis" <technews@kangaroologic.com> writes:
"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message:
cbegin()/cend() aren't all that useful unless they also work with the standard library containers. If it's never going to happen for the standard containers, why bother putting it into Boost? Something like "as_const(c)" is a totally different story, of course.
Why can't const_begin be implemented as follows (for standard library containers):
template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); }
For one thing you can't use static_cast to change constness. I can't imagine why you'd want this first overload.
template<typename Range> typename range_const_iterator<X>::type const_begin(const Range& rng) { return begin(rng); }
That one works. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u3c1jhvz5.fsf@boost-consulting.com...
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); }
For one thing you can't use static_cast to change constness.
Are you sure? The expression const Range& r(rng) is well formed, I believe, so static_cast<const Range&>(rng) should be okay.
I can't imagine why you'd want this first overload.
You're right that it's superflous, given the second overload. But you should still be able to imagine why I wrote it. ;-) I forgot that X::iterator must be convertible to X::const_iterator, and that you can take advantage of more implicit conversions when you switch from member functions to non-member functions. Jonathan

From: "Jonathan Turkanis" <technews@kangaroologic.com>
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u3c1jhvz5.fsf@boost-consulting.com...
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); }
For one thing you can't use static_cast to change constness.
Are you sure? The expression
Yep. See 5.2.9. You'll see what static_cast can do, and then 5.2.9/3 specifically excludes any other conversions. Modifying cv qualification is not among the things static_cast can do. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" <stewart@sig.com> wrote in message:
From: "Jonathan Turkanis" <technews@kangaroologic.com>
"David Abrahams" <dave@boost-consulting.com> wrote:
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); }
For one thing you can't use static_cast to change constness.
Are you sure? The expression
Yep. See 5.2.9. You'll see what static_cast can do, and then 5.2.9/3 specifically excludes any other conversions.
The above cast seems to be permitted under 5.2.9/2, for the reason you snipped, namely that const Range& r(rng) is well formed.
Modifying cv qualification is not among the things static_cast can do.
Then why use the language "The static_cast operator shall not cast away constness" (5.2.9/1)? Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> writes:
"Rob Stewart" <stewart@sig.com> wrote in message:
From: "Jonathan Turkanis" <technews@kangaroologic.com>
"David Abrahams" <dave@boost-consulting.com> wrote:
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); }
For one thing you can't use static_cast to change constness.
Are you sure? The expression
Yep. See 5.2.9. You'll see what static_cast can do, and then 5.2.9/3 specifically excludes any other conversions.
The above cast seems to be permitted under 5.2.9/2, for the reason you snipped, namely that
const Range& r(rng)
is well formed.
Modifying cv qualification is not among the things static_cast can do.
Then why use the language "The static_cast operator shall not cast away constness" (5.2.9/1)?
I was wrong. Sorry. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
"Rob Stewart" <stewart@sig.com> wrote in message:
From: "Jonathan Turkanis" <technews@kangaroologic.com>
"David Abrahams" <dave@boost-consulting.com> wrote:
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
template<typename Range> typename range_const_iterator<X>::type const_begin(Range& rng) { return begin(static_cast<const Range&>(rng)); }
For one thing you can't use static_cast to change constness.
Are you sure? The expression
Yep. See 5.2.9. You'll see what static_cast can do, and then 5.2.9/3 specifically excludes any other conversions.
The above cast seems to be permitted under 5.2.9/2, for the reason you snipped, namely that
const Range& r(rng)
is well formed.
Modifying cv qualification is not among the things static_cast can do.
Then why use the language "The static_cast operator shall not cast away constness" (5.2.9/1)?
I was wrong. Sorry.
So was I, it seems. You can use static_cast to *add* const. Thanks Jonathan! Having said that, why not use const_cast and avoid the confusion in the first place? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" <stewart@sig.com> wrote in message:
From: David Abrahams <dave@boost-consulting.com>:
I was wrong. Sorry.
So was I, it seems. You can use static_cast to *add* const. Thanks Jonathan!
Having said that, why not use const_cast and avoid the confusion in the first place?
When I was writing it I initially typed 'const_cast', but then thought to myself: why use my big guns if I don't have to? ;-) Jonathan

Jonathan Turkanis wrote:
When I was writing it I initially typed 'const_cast', but then thought to myself: why use my big guns if I don't have to? ;-)
For clarity -- to tell the reader that you intended to modify the const-ness. -- Dick Hadsell 914-259-6320 Fax: 914-259-6499 Reply-to: hadsell@blueskystudios.com Blue Sky Studios http://www.blueskystudios.com 44 South Broadway, White Plains, NY 10601

Richard Hadsell <hadsell@blueskystudios.com> writes:
Jonathan Turkanis wrote:
When I was writing it I initially typed 'const_cast', but then thought to myself: why use my big guns if I don't have to? ;-)
For clarity -- to tell the reader that you intended to modify the const-ness.
static_cast is a bigger gun than const_cast. At least const_cast cant violate data layout, and unless there is actually a constant object, won't result in undefined behavior. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:umzzl3pvk.fsf@boost-consulting.com...
Richard Hadsell <hadsell@blueskystudios.com> writes:
Jonathan Turkanis wrote:
When I was writing it I initially typed 'const_cast', but then thought to myself: why use my big guns if I don't have to? ;-)
For clarity -- to tell the reader that you intended to modify the const-ness.
static_cast is a bigger gun than const_cast. At least const_cast cant violate data layout, and unless there is actually a constant object, won't result in undefined behavior.
Good point. I guess part of the reason I avoid const_cast whenever possible is that people look upon it suspiciously, even if it's only adding cv-qualification. Maybe people should be more suspicious of static_cast. Jonathan

From: "Jonathan Turkanis" <technews@kangaroologic.com>
"David Abrahams" <dave@boost-consulting.com> wrote in message news:umzzl3pvk.fsf@boost-consulting.com...
Richard Hadsell <hadsell@blueskystudios.com> writes:
Jonathan Turkanis wrote:
When I was writing it I initially typed 'const_cast', but then thought to myself: why use my big guns if I don't have to? ;-)
For clarity -- to tell the reader that you intended to modify the const-ness.
static_cast is a bigger gun than const_cast. At least const_cast cant violate data layout, and unless there is actually a constant object, won't result in undefined behavior.
Good point. I guess part of the reason I avoid const_cast whenever possible is that people look upon it suspiciously, even if it's only adding cv-qualification. Maybe people should be more suspicious of static_cast.
As Dave points out, there is much more possible with static_cast, so it should be viewed with suspicion. Casting away constness is always worth a second look (including asking why mutable wasn't used), and adding const is certainly unusual. Therefore, I understand why you would consider const_cast to be more of a problem than static_cast. The bottom line is any cast should be considered suspect and should, in most contexts, be documented. (That allows a future maintainer the opportunity to remove it if an alternative is found.) -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Richard Hadsell wrote:
For clarity -- to tell the reader that you intended to modify the const-ness.
If I see const_cast, I usually expect it to cast away const-ness, not add it. In my opinion, using a cast to add const is really a pretty unusual thing to do so 'as_const' might be the clearest way of showing your intent. Of course, it requires the reader to know what it means. Daniel

On Wed, Sep 15, 2004 at 01:35:11PM -0500, Doug Gregor wrote:
On Sep 15, 2004, at 1:09 PM, Thorsten Ottosen wrote:
"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message news:DD33A4E0-0733-11D9-8C97-000A95B0EC64@cs.indiana.edu... | | On Sep 15, 2004, at 10:09 AM, Thorsten Ottosen wrote:
| > Given the framework in boost.range these would be absolutely *trivial* | > to add. | > | > 1st vote: for or against adding these? | | Against. If the C++ committee likes them, we can add them into a later | revision of Boost.
Ok, but doesn't it usually work the way that things go into boost first? If not for anything else, then to see if the stuff works in practice?
cbegin()/cend() aren't all that useful unless they also work with the standard library containers. If it's never going to happen for the standard containers, why bother putting it into Boost? Something like "as_const(c)" is a totally different story, of course.
Are you sure about this? What about: template<typename ContainerT> typename ContainerT::const_iterator const_begin(const ContainerT& C) { return C.begin(); } This should do exactly what we want. To sumarize, I like the idea of const_begin()/end() in this wording. Regards, Pavol

Go for the const_begin versions - crbegin is dreadful. Write-once - read many... Paul | -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of Thorsten Ottosen | Sent: 15 September 2004 16:10 | To: boost@lists.boost.org | Subject: [boost] [boost.range] late addition, votes needed | | Dear All, | | In the pre-redmond mailing Walter Brown discusses the | possibility of adding | these members to standard container classes: | | const_iterator cbegin(); | const_iterator cend(); | const_reverse_iterator crbegin(); | const_reverse_iterator crbegin(); | | The motiviation is that we want to be able to say explicitly | "give me a const | iterator" without doing ugly casts. | IMO a sound idea. | | Given the framework in boost.range these would be absolutely | *trivial* to add. | | 1st vote: for or against adding these? | | 2nd vote: which naming scheme to use: | | a: cbegin(), cr_begin() | | b: const_begin(); const_rbegin(); | | The motivation for chosing the latter could be that "cr" | contracttions become | harder to read. | | Let me know what ya think. | | best regards | | Thorsten

From: "Thorsten Ottosen" <nesotto@cs.auc.dk>
In the pre-redmond mailing Walter Brown discusses the possibility of adding these members to standard container classes:
const_iterator cbegin(); const_iterator cend(); const_reverse_iterator crbegin(); const_reverse_iterator crbegin();
The motiviation is that we want to be able to say explicitly "give me a const iterator" without doing ugly casts. IMO a sound idea.
Agreed.
Given the framework in boost.range these would be absolutely *trivial* to add.
1st vote: for or against adding these?
Yes.
2nd vote: which naming scheme to use:
a: cbegin(), cr_begin()
b: const_begin(); const_rbegin();
Unquestionably, "b." That version parallels "iterator" versus "const_iterator," not to mention being more readable. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Thorsten Ottosen wrote:
1st vote: for or against adding these?
For.
2nd vote: which naming scheme to use:
a: cbegin(), cr_begin()
b: const_begin(); const_rbegin();
b! cr_begin is wrong (where does the underscore come from?), it should have to be crbegin instead, which is ugly.
I wonder whether it's better to say
cbegin(x)
or
begin(as_const(x))
The latter is certainly more general.
It's more general but it has a big usability issue: it's hard for me to find a rationale that I can get a reverse_iterator by calling "rbegin" but have to apply something to the container to get a const_iterator. Whatever the best solution is, there should be the same concept for const and reverse for the user! Stefan

Stefan Slapeta <stefan_nospam_@slapeta.com> writes:
Thorsten Ottosen wrote:
1st vote: for or against adding these?
For.
2nd vote: which naming scheme to use: a: cbegin(), cr_begin() b: const_begin(); const_rbegin();
b! cr_begin is wrong (where does the underscore come from?), it should have to be crbegin instead, which is ugly.
I wonder whether it's better to say
cbegin(x)
or
begin(as_const(x))
The latter is certainly more general.
It's more general but it has a big usability issue: it's hard for me to find a rationale that I can get a reverse_iterator by calling "rbegin" but have to apply something to the container to get a const_iterator.
Whatever the best solution is, there should be the same concept for const and reverse for the user!
Just because the original designers made the mistake of building in rbegin() and rend() accessors, it doesn't mean we should perpetuate the same mistake for consistency. Orthogonality is better. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6uvhw8w.fsf@boost-consulting.com... | > > I wonder whether it's better to say | > > | > > cbegin(x) | > > | > > or | > > | > > begin(as_const(x)) | > > | > > The latter is certainly more general. | > > | > | > It's more general but it has a big usability issue: it's hard for me | > to find a rationale that I can get a reverse_iterator by calling | > "rbegin" but have to apply something to the container to get a | > const_iterator. | > | > Whatever the best solution is, there should be the same concept for | > const and reverse for the user! | | Just because the original designers made the mistake of building in | rbegin() and rend() accessors, it doesn't mean we should perpetuate | the same mistake for consistency. no, not necessarily | Orthogonality is better. as_const() woul be othogonal to begin(), rbegin(), but there is a clear difference between changing constness and changing traversal direction. The only "mistake" of rbegin() is that is it member even though it does not have to be. br Thorsten

David Abrahams wrote:
Just because the original designers made the mistake of building in rbegin() and rend() accessors, it doesn't mean we should perpetuate the same mistake for consistency.
I wouldn't call it a mistake. rbegin/rend isolate the user from the somewhat counter-intuitive notion that rbegin() is obtained from end(). I like the proposed cbegin/crbegin member functions. There is a vast audience of programmers that value ease of use and consistency above orthogonality.

Peter Dimov wrote:
[...] There is a vast audience of programmers that value ease of use and consistency above orthogonality.
I second that! Beside that, I've no problem if both member and free functions are provided; I also wouldn't bother if one could write both x.const_rbegin _and_ rbegin(as_const(x)). There are good reasons for both. Stefan

"Peter Dimov" <pdimov@mmltd.net> writes:
David Abrahams wrote:
Just because the original designers made the mistake of building in rbegin() and rend() accessors, it doesn't mean we should perpetuate the same mistake for consistency.
I wouldn't call it a mistake. rbegin/rend isolate the user from the somewhat counter-intuitive notion that rbegin() is obtained from end().
Or they confuse the user who thinks "the iterator goes backwards, therefore I should start from rend() and increment until rbegin()."
I like the proposed cbegin/crbegin member functions. There is a vast audience of programmers that value ease of use and consistency above orthogonality.
Convenience functions are fine with me, actually. Still, I'd be reluctant to do this without making the more general components available. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Hi, I have counted the votes as follows: For const_begin() etc. - Jonathan Turkanis - Pavol Droba - Paul Bristow - Rob Stewart - Stefan Slapeta (*) - Peter Dimov - Me Not for or for as_const(): - Dave Abrahams - Doug Gregor - John Torjo - Jeff Flinn So I will add the functions to the range library. Whether somebody should add as_const() to boost.util is up to them. (*) At least that is what I could figure out from your message...it wont change the outcome of the vote.
participants (14)
-
Daniel James
-
David Abrahams
-
Doug Gregor
-
Jeff Flinn
-
John Torjo
-
Jonathan Turkanis
-
Paul A Bristow
-
Pavol Droba
-
Peter Dimov
-
Richard Hadsell
-
Rob Stewart
-
Stefan Slapeta
-
Stefan Slapeta
-
Thorsten Ottosen