iterator question

V

Victor Bazarov

Roel said:
The following will not compile under gcc 3.2.2:

#include <string>
#include <vector>
#include <iostream>
#include <ctype.h>

class A
{
public:
int a;
};

int main(int argc, char* argv[])
{
A a1, a2, a3;

std::vector<A> alist;
alist.push_back(a1);
alist.push_back(a2);
alist.push_back(a3);

for (int i = 0 ; i < alist.size() ; i++) {
A* pntr = const_cast<A*>(alist.begin() + i);

What's this ugliness for?

A* pntr = & alist;
std::cout << pntr->a << std::endl;

And why do you need a pointer anyway? Why not just write

std::cout << alist.a << std::end;

???
}

return 0;
}


The error message is

test.cpp: In function `int main(int, char**)':
test.cpp:22: invalid const_cast from type `__gnu_cxx::__normal_iterator<A*,
std::vector<A, std::allocator<A> > >' to type `A*'

But when I change the const_cast line to

A* pntr = const_cast<A*>(&(*(alist.begin() + i)));

it will work as expected (note the extra dereference and address-of
operator). But this obviously looks ugly - what is the correct way to do
this? Isn't the first form supposed to convert to an A* directly? Thanks.

No, it's not. An iterator is an iterator. It is its own type, not
a constant pointer. And it doesn't have to be convertible to a pointer
(contrary to what some might want to believe).

Victor
 
K

Kevin Goodsell

Roel said:
Hello all,

The following will not compile under gcc 3.2.2:

#include <string>
#include <vector>
#include <iostream>
#include <ctype.h>

class A
{
public:
int a;
};

int main(int argc, char* argv[])
{
A a1, a2, a3;

std::vector<A> alist;
alist.push_back(a1);
alist.push_back(a2);
alist.push_back(a3);

for (int i = 0 ; i < alist.size() ; i++) {
A* pntr = const_cast<A*>(alist.begin() + i);

You can't cast an iterator to a pointer and expect it to work. Try this
instead:

A* pntr = &alist;

Why are you using iterator arithmetic instead of indexing anyway?
Indexing gives considerably cleaner code.
std::cout << pntr->a << std::endl;
}

return 0;
}


The error message is

test.cpp: In function `int main(int, char**)':
test.cpp:22: invalid const_cast from type `__gnu_cxx::__normal_iterator<A*,
std::vector<A, std::allocator<A> > >' to type `A*'

But when I change the const_cast line to

A* pntr = const_cast<A*>(&(*(alist.begin() + i)));

it will work as expected (note the extra dereference and address-of
operator). But this obviously looks ugly - what is the correct way to do
this? Isn't the first form supposed to convert to an A* directly? Thanks.

There is no such conversion. The "ugly" indirect method you gave is the
only portable way to get a pointer from an iterator.

-Kevin
 
R

Roel

Hello all,

The following will not compile under gcc 3.2.2:

#include <string>
#include <vector>
#include <iostream>
#include <ctype.h>

class A
{
public:
int a;
};

int main(int argc, char* argv[])
{
A a1, a2, a3;

std::vector<A> alist;
alist.push_back(a1);
alist.push_back(a2);
alist.push_back(a3);

for (int i = 0 ; i < alist.size() ; i++) {
A* pntr = const_cast<A*>(alist.begin() + i);
std::cout << pntr->a << std::endl;
}

return 0;
}


The error message is

test.cpp: In function `int main(int, char**)':
test.cpp:22: invalid const_cast from type `__gnu_cxx::__normal_iterator<A*,
std::vector<A, std::allocator<A> > >' to type `A*'

But when I change the const_cast line to

A* pntr = const_cast<A*>(&(*(alist.begin() + i)));

it will work as expected (note the extra dereference and address-of
operator). But this obviously looks ugly - what is the correct way to do
this? Isn't the first form supposed to convert to an A* directly? Thanks.

cheers,

roel
 
R

Ron Natalie

Roel said:
Hello all,

The following will not compile under gcc 3.2.2:
And rightfully so.
A* pntr = const_cast<A*>(alist.begin() + i);

Hold the phone. Iterators are NOT necessarily pointers and why on earth
are you screwing around with const cast here. You can't expect to convert
an iterator directly to a pointer (although it will work on vectors coincidentally
on many systems).

for(vector<A>::iterator pntr = alist.begin(); pntr != alist.end(); ++pntr)
cout << pntr->a << "\n";

is what you want.
A* pntr = const_cast<A*>(&(*(alist.begin() + i)));

This is legitimate but convoluted.
alist.begin() + i
is legitmate iterator which you can dereference
and that yields an A object which you can take the address of.
You don't even need the const cast.

A* pntr = & (alist.begin());

But even that is more than you want to do.
 
R

Ron Natalie

Roel said:
Well I was trying to get some open source code to compile, and the author
used the iterator indexing. I figured 'he must have had a special reason
for doing this funny stuff' but apparantly not. Thanks for your answer!

He's evidentally not very good at C++.
 
R

Roel

Kevin said:
You can't cast an iterator to a pointer and expect it to work. Try this
instead:
A* pntr = &alist;
Why are you using iterator arithmetic instead of indexing anyway?
Indexing gives considerably cleaner code.


Well I was trying to get some open source code to compile, and the author
used the iterator indexing. I figured 'he must have had a special reason
for doing this funny stuff' but apparantly not. Thanks for your answer!

cheers,

roel
 
R

Roel

Victor said:
What's this ugliness for?
A* pntr = & alist;
std::cout << pntr->a << std::endl;
And why do you need a pointer anyway? Why not just write
std::cout << alist.a << std::end;
???


Well it was in the code as I got it (open source package) so I figured that
who wrote it would know what they were doing. I'm going to change it to the
more direct approach like you and others suggested. Thanks for your answer!
No, it's not. An iterator is an iterator. It is its own type, not
a constant pointer. And it doesn't have to be convertible to a pointer
(contrary to what some might want to believe).

Hmm I think that I've been mis-educated by using MSVC too much ;)


cheers,

roel
 
N

Noah Roberts

Roel said:
Kevin said:
You can't cast an iterator to a pointer and expect it to work. Try this
instead:
A* pntr = &alist;
Why are you using iterator arithmetic instead of indexing anyway?
Indexing gives considerably cleaner code.



Well I was trying to get some open source code to compile, and the author
used the iterator indexing. I figured 'he must have had a special reason
for doing this funny stuff' but apparantly not. Thanks for your answer!

cheers,

roel


What program?
 
R

Roel

Noah said:
What program?

Well I don't want to put anyone down, I think that the person who wrote it
did a good job (it's fully functional and all after all), but the program
can be downloaded at www.sf.net/projects/dbg2. The files I used are in
dbg-2.10rc2.linux.tar.gz. The program is a PHP debugger for Linux and
Windows.

cheers,

roel
 
N

Noah Roberts

Roel said:
Well I don't want to put anyone down, I think that the person who wrote it
did a good job (it's fully functional and all after all), but the program
can be downloaded at www.sf.net/projects/dbg2. The files I used are in
dbg-2.10rc2.linux.tar.gz. The program is a PHP debugger for Linux and
Windows.


Here is the only thing I could find that even resembles the OP code.
CommandList derives from std::vector<CommandEntry>

CommandEntry *CommandList::lookup_cmd(const char *cmd) const {
int L, H, i, cmp;
CommandEntry *entry;
L = 0;
H = end() - begin() - 1;
while (L <= H) {
i = (L + H) >> 1;
entry = const_cast<CommandEntry *>(begin() + i);
cmp = safestricmp(entry->name, cmd);
if (cmp < 0) {
L = i + 1;
}
else {
if (cmp == 0) return (entry);
H = i - 1;
}
}
return NULL;
}
 
R

Roel

Noah said:
Here is the only thing I could find that even resembles the OP code.
CommandList derives from std::vector<CommandEntry>

Yes, exactly, that is the place, in command.cpp around line 293 if i
remember correctly. I just made up a small example that looked like this,
but that was short enough to post. I hope I didn't butcher it up too much
and that the situation is still the same :) While we're on the discussion,
can you tell me what the bitshift does in the code below? Thanks.

cheers,

roel
 
K

Kevin Goodsell

Roel said:
Yes, exactly, that is the place, in command.cpp around line 293 if i
remember correctly. I just made up a small example that looked like this,
but that was short enough to post. I hope I didn't butcher it up too much
and that the situation is still the same :) While we're on the discussion,
can you tell me what the bitshift does in the code below? Thanks.

Divides by 2 to find the midpoint. Looks like it's a binary search,
which makes me wonder why the author didn't use existing standard
library functions and/or containers instead.

-Kevin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top