For Programmers: Free Programming Magazines  


Home > Archive > VC STL > February 2005 > [VC 7.1] const_reverse_iterator problem









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author [VC 7.1] const_reverse_iterator problem
Aurélien REGAT-BARREL

2005-02-14, 9:11 pm

Hi,
I don't understand why VC++ 7.1 can't compile the following code:

#include <set>

using namespace std;

int main(void)
{
set<int> s1;


for (
set<int>::const_reverse_iterator i = s1.rbegin();
i != s1.rend(); // error 2676
++i )
{
}

// ok
set<int>::const_reverse_iterator a = s1.rend();

// ok
for (
set<int>::const_reverse_iterator i = s1.rbegin(), end =
s1.rend();
i != end;
++i )
{
}

// ok
for (
set<int>::const_reverse_iterator i = s1.rbegin();
i != set<int>::const_reverse_iterator( s1.rend() );
++i )
{
}

// ok
const set<int> s2;
for (
set<int>::const_reverse_iterator i = s2.rbegin();
i != s2.rend();
++i )
{
}

return 0;
}



The error is:

test.cpp(12) : error C2784: 'bool std::operator !=(const std::_Tree<_Traits>
&,c
onst std::_Tree<_Traits> &)' : could not deduce template argument for 'const
std
::_Tree<_Traits> &' from 'std::set<_Kty>::const_reverse_iterator'
with
[
_Kty=int
]

There is no problem with g++.

It is not a real problem for me, but I would like to understand what is
wrong.
Thanks.

--
Aurélien REGAT-BARREL


Tom Widmer

2005-02-14, 9:11 pm

Aurélien REGAT-BARREL wrote:

>
> The error is:
>
> test.cpp(12) : error C2784: 'bool std::operator !=(const std::_Tree<_Traits>
> &,c
> onst std::_Tree<_Traits> &)' : could not deduce template argument for 'const
> std
> ::_Tree<_Traits> &' from 'std::set<_Kty>::const_reverse_iterator'
> with
> [
> _Kty=int
> ]
>
> There is no problem with g++.
>
> It is not a real problem for me, but I would like to understand what is
> wrong.


This is because of a defect in the standard:
http://www.open-std.org/jtc1/sc22/w...active.html#280
http://www.open-std.org/jtc1/sc22/w...efects.html#179

I assume GCC implements the solution to the defect - check the gcc
headers (they usually include the defect number in a comment when
they've made such a fix).

Tom
Aurélien REGAT-BARREL

2005-02-14, 9:11 pm

> This is because of a defect in the standard:
> http://www.open-std.org/jtc1/sc22/w...active.html#280
> http://www.open-std.org/jtc1/sc22/w...efects.html#179


Thank you for the links. But I still don't understand.
I'm not trying to compare 2 different kinds of iterators (reverse vs
non-reverse, or const vs non-const), but 2 reverse_const_iterator.
Since the following code compiles well:

set<int> s;
set<int>::const_reverse_iterator a = s.rbegin();
set<int>::const_reverse_iterator b = s.rend();
if ( a != b ) {}

I don't understand why this one is problematic :

if ( a != s.rend() ) {}

An overloaded version of rend() which returns a const_reverse_iterator
exists, that's why I don't understand where is the problem.

--
Aurélien REGAT-BARREL


Ulrich Eckhardt

2005-02-14, 9:11 pm

Aurélien REGAT-BARREL wrote:
> I'm not trying to compare 2 different kinds of iterators (reverse vs
> non-reverse, or const vs non-const), but 2 reverse_const_iterator.


Yes you are ...

> Since the following code compiles well:
>
> set<int> s;
> set<int>::const_reverse_iterator a = s.rbegin();
> set<int>::const_reverse_iterator b = s.rend();


The calls to rbegin() and rend() both call the non-const(!) overload. There
is however a cctor of const_reverse_iterator that takes a reverse_iterator.

> if ( a != b ) {}


Of course, operator!=( const_rev_iter, const_rev_iter) exists, so this
works.

> I don't understand why this one is problematic:
>
> if ( a != s.rend() ) {}


This doesn't work, as rend() is again the non-const version and there is no
operator!=( const_rev_iter, rev_iter).
Workarounds:
- make sure the const version is called by e.g.
if( a != static_cast<set<int> const&>(s).rend())
{...}
- convert to a const iterator before comparing:
if( a != static_cast<const_rev_iter>(s.rend()))
{...}
- for for-loops, the most elegant (and possibly even more performant!)
solution is to create two named iterators. The general pattern is this:
for( container::iterator it=cont.begin(), end=cont.end();
it!=end;
++it)
{...}

happy hacking

Uli

Stephen Howe

2005-02-14, 9:11 pm

>> set<int> s;
>
> The calls to rbegin() and rend() both call the non-const(!) overload.


Why? I would expect the const overload version to be called.
That goes against the principle of least atonishment.
You would not get that with vector, deque, list, so why set?

Thanks

Stephen Howe


Igor Tandetnik

2005-02-14, 9:11 pm

"Stephen Howe" <sjhoweATdialDOTpipexDOTcom> wrote in message
news:OVZa2$mAFHA.612@TK2MSFTNGP09.phx.gbl
>
> Why? I would expect the const overload version to be called.
> That goes against the principle of least atonishment.
> You would not get that with vector, deque, list, so why set?


Why would you expect a const iterator from s.rbegin() when s itself is
non-const? Why would you want to prohibit, say,

s.rbegin()->nonKeyMember = 1;

What makes you thing vector, deque and list are any different in this
regard?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Stephen Howe

2005-02-14, 9:11 pm

>>> The calls to rbegin() and rend() both call the non-const(!) overload.
>
> Why would you expect a const iterator from s.rbegin() when s itself is
> non-const?


Okay I see now. I agree.
Thanks.

Stephen Howe


Aurélien REGAT-BARREL

2005-02-14, 9:11 pm

> >>> The calls to rbegin() and rend() both call the non-const(!) overload.

That's what I missed.

Thank you all.

--
Aurélien REGAT-BARREL


Jerry Coffin

2005-02-14, 9:11 pm

In article <OVZa2$mAFHA.612@TK2MSFTNGP09.phx.gbl>, "Stephen Howe"
<sjhoweATdialDOTpipexDOTcom> says...
>
> Why? I would expect the const overload version to be called.
> That goes against the principle of least atonishment.
> You would not get that with vector, deque, list, so why set?


Remember that C++ doesn't use the return type for overload
resolution. Here you're assigning to return a const_iterator, but
you're calling rbegin() on s, which is a non-const set. Since s isn't
const, you call set::rbegin instead of s::rbegin() const.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com