Sign in to follow this  
wforl

iter to address of item

Recommended Posts

wforl    169
hmm, can anyone tell me whats wrong the below code header
#ifndef UI_ITEM
#define UI_ITEM

#include "globalSettings.h"
#include "loadTexture.h"

class UI_item
{
public:
	UI_item(float posx, float posy, float posz, float scalex, float scaley, float scalez, 
		IDirect3DVertexBuffer9* VB, IDirect3DIndexBuffer9* IB, 
		char *imageLocation );
	~UI_item();

	void display();

private:

	D3DXMATRIX transform;
	IDirect3DVertexBuffer9* VB;		
	IDirect3DIndexBuffer9* IB;
	IDirect3DTexture9*     image;
	static std::vector <UI_item> UI_list;
};
#endif


cpp
#include "UI_Item.h"

extern IDirect3DDevice9* gd3dDevice;
std::vector <UI_item> UI_item::UI_list;	//declare the static member

UI_item::UI_item(float posx, float posy, float posz, float scalex, float scaley, float scalez, 
		IDirect3DVertexBuffer9* _VB, IDirect3DIndexBuffer9* _IB, 
		char *imageLocation )
{
	D3DXMATRIX statsWorld;
	D3DXMATRIX statsScale;
	D3DXMatrixIdentity(&statsWorld);
	D3DXMatrixIdentity(&statsScale);

	D3DXMatrixTranslation(&statsWorld, posx, posy, posz);
	D3DXMatrixScaling(&statsScale, scalex, scaley, scalez);
	transform = statsWorld * statsScale;
	VB = _VB;
	IB = _IB;
	loadTexture(gd3dDevice, imageLocation, &image);

	UI_list.push_back((*this));
	
}


UI_item::~UI_item()
{
}

void UI_item::display()
{
	std::vector <UI_item>::iterator iter = UI_list.begin();
	while (iter != UI_list.end())
		{
			gd3dDevice->SetTexture(0, iter->image);
			gd3dDevice->SetTransform(D3DTS_WORLD, iter->&transform);
			gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);
			iter++;
		}

}


im getting the following error 1>d:\c++\my game\ui_item.cpp(37) : error C2059: syntax error : '&' which points to this line [B]gd3dDevice->SetTransform(D3DTS_WORLD, iter->&transform);[/B]

Share this post


Link to post
Share on other sites
shurcool    439
Maybe you meant to write this:
gd3dDevice->SetTransform(D3DTS_WORLD, &(iter->transform));
If what you need to do is pass the address of the transform object as the 2nd param to SetTransform.

Note the brackets aren't necessary due to precedence of operators (& operator has lower precedence than ->), but used to illustrate the idea.

Share this post


Link to post
Share on other sites
SpreeTree    396
iter->&transform is not legal syntax. I am assuming you are trying to pass the address of transform to gd3dDevice->SetTransform, in which case you need pass the address of the object - &(pointer->transform).

One problem you may encounter is that you are assuming std::vector <UI_item>::iterator is the same as UI_item* which may be the case on some compilers, but not on others. You need to dereference the iterator before you can use it to make it complient with all versions of the STL.

So you will probably want something like...

{
// Get the actual UI item that we are using
UI_item& uiItem = (*itor);

// More code..

gd3dDevice->SetTexture(0, uiItem.image);
gd3dDevice->SetTransform(D3DTS_WORLD, &(uiItem.transform));

// More code..

}

This is because, depending on the version of the STL being used or the compiler settings, an iterator may not be a basic pointer, but another templated type (which allows for iterator checks and debugging for example).

Share this post


Link to post
Share on other sites
shurcool    439
SpreeTree, as far as I'm aware, most (if not all) iterators overload the -> operator to return a pointer to the current object in the same way they overload the * operator to return a reference to the current object.

So it should be completely equivalent to use either one.
std::vector<MyCustomPlayerClass> vec;
vec.push_back(MyCustomPlayerClass("Player 1"));
std::vector<MyCustomPlayerClass>::iterator it1;

// Use a reference
for (it1 = vec.begin(); it1 != vec.end(); ++it1)
cout << (*it).GetName();

// Use a pointer
for (it1 = vec.begin(); it1 != vec.end(); ++it1)
cout << it->GetName();

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by shurcool
SpreeTree, as far as I'm aware, most (if not all) iterators overload the -> operator to return a pointer to the current object in the same way they overload the * operator to return a reference to the current object.


You are correct, most implementations of the STL will over-ride operator->, but using is can lead people to believe that vector<>::iterator is a pointer when in-fact it is not. I have encountered a lot of people, new to STL, who assume that because an iterator behaves like a pointer, they can treat it as such.

By stressing that it isn't (and some implementations of the STL do enforce that), you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer [edit] because you know iterators are not pointers, so you have a better chance of understanding why errors are occuring [/edit].

Also, getting into a habit of dereferencing an iterator makes it easier to use things like vector<MyObject*>::iterator, as you then have a more consistent code base when it comes to the STL.

[Edited by - SpreeTree on March 24, 2008 4:31:57 PM]

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by SpreeTree
You are correct, most implementations of the STL will over-ride operator->, but using is can lead people to believe that vector<>::iterator is a pointer when in-fact it is not.


All non-output iterators implement operator ->. It's required by the C++ Standard for input iterators, forward iterators, bidirectional iterators and random access iterators. By definition -> is usable on all STL container iterators. If you couldn't then they wouldn't be iterators.

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by SiCrane
All non-output iterators implement operator ->. It's required by the C++ Standard for input iterators, forward iterators, bidirectional iterators and random access iterators. By definition -> is usable on all STL container iterators. If you couldn't then they wouldn't be iterators.


Fair point, unfortunately I have often had to use STL implementations that haven't been fully implemented and unfortunatly not everything meets the standard as maybe it should. Regardless of whether it is implemented or not, the use of it does lead to issues, which I pointed out in my earlier post.

Share this post


Link to post
Share on other sites
SiCrane    11839
Really? So what compilers have you used that didn't implement operator-> on standard library container iterators?

Share this post


Link to post
Share on other sites
Bregma    9199
Quote:
Original post by shurcool
SpreeTree, as far as I'm aware, most (if not all) iterators overload the -> operator to return a pointer to the current object in the same way they overload the * operator to return a reference to the current object.


You are incorrect: the selection operator (operator->()) is supposed to select a member of the underlying typename value_type of the iterator. It does not return a pointer (unless of course the member of the underlying typename value_type is a pointer). All iterators provided by the standard library, where they provide that operator, provide that functionality.

The dereference operator (operator*()) returns an object of the underlying typename reference or typename const_reference. All iterators provide by the standard library, where they provide that operator, provide that functionality.

Not all iterator suppor the notion of a "current object." For example, a standard output iterator.

--smw

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by SiCrane
Really? So what compilers have you used that didn't implement operator-> on standard library container iterators?


In the past couple of years I have personally used at least one (maybe more) platform specific STL implementation that didn't support operator-> on their (non-pointer) iterators (well, their non-pointer iterators were generally messed up at the time though I do suspect it has gotten a lot better recently).

Unfortunately, under NDA I'm not going to specifically name the platforms or compilers.

Share this post


Link to post
Share on other sites
SiCrane    11839
So in other words, you want people to change their programming habits for a case so rare that you can't actually name a situation where it will occur?

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by SiCrane
So in other words, you want people to change their programming habits for a case so rare that you can't actually name a situation where it will occur?


Not at all. I always recommend dereferencing the iterator for the main reasons I stated in my previous posts.

Quote:
Original post by SpreeTree
using is can lead people to believe that vector<>::iterator is a pointer when in-fact it is not. I have encountered a lot of people, new to STL, who assume that because an iterator behaves like a pointer, they can treat it as such.

Quote:
Original post by SpreeTree
you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer

Quote:
Original post by SpreeTree
getting into a habit of dereferencing an iterator makes it easier to use things like vector<MyObject*>::iterator, as you then have a more consistent code base when it comes to the STL.


Now you could say some of that is irrelevant, and I'm sure some people will, but from experience of working with people who are new to STL (and in both hobbyist and professional life that can be a lot of people), the above points have helped a lot.

As for rare cases that I "can't actually name" I'm sorry about that, but it's the situation in which I (and plenty of other people) work. These rare cases have swayed my opinion on the use of STL, but it's bitten more people than me in the ass before. It's just another reason I belive dereferencing is better than using a raw iterator.

Share this post


Link to post
Share on other sites
SiCrane    11839
Given the small fact that random access iterators support the same set of semantic operations that pointers do, such as indexing, iterator arithmetic and so on (pointers being a kind of random access iterator), and using this information is quite often useful in writing efficient STL code, it's hard to see where suggesting that you ignore the fact that iterators do provide this functionality is good advice.

Especially when one of your own points that you quoted yourself
Quote:

you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer

directly contradicts this advice.

Quote:
Original post by SpreeTree
getting into a habit of dereferencing an iterator makes it easier to use things like vector<MyObject*>::iterator, as you then have a more consistent code base when it comes to the STL.

So would you also suggest making it a habit to dereference pointers to make it easier to use things like MyObject **, as then you have a more consistent code base when it comes to pointer code?

Share this post


Link to post
Share on other sites
the_edd    2109
Quote:
Original post by SiCrane
All non-output iterators implement operator ->. It's required by the C++ Standard for input iterators, forward iterators, bidirectional iterators and random access iterators. By definition -> is usable on all STL container iterators. If you couldn't then they wouldn't be iterators.


Actually, that's not true in the strictest sense. I was bitten by this. There's some weasel wording in the standard (which I don't have to hand at the moment unfortunately) that says an input iterator of type X only needs to support operator-> if (*x).m is well formed where x is an instance of X.

Concrete example: std::istreambuf_iterator<char> does not support operator->.

Quote:
Original post by Bregma
You are incorrect: the selection operator (operator->()) is supposed to select a member of the underlying typename value_type of the iterator. It does not return a pointer (unless of course the member of the underlying typename value_type is a pointer). All iterators provided by the standard library, where they provide that operator, provide that functionality.


An overloaded operator-> must return a pointer-to-value_type, or an object whose type implements such an operator->.

Share this post


Link to post
Share on other sites
SiCrane    11839
Well duh. What would you expect operator -> to do on a std::istreambuf_iterator<char> anyways? That's like complaining you can't write 5->1.

Share this post


Link to post
Share on other sites
the_edd    2109
Quote:
Original post by SiCrane
Well duh. What would you expect operator -> to do on a std::istreambuf_iterator<char> anyways? That's like complaining you can't write 5->1.


Well indeed, but the point is there's no requirement for an operator->(), as you asserted. Note that this is even true for the case where you have an iterator that refers to a *compound* object of a type that has no members.

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by SiCrane
Especially when one of your own points that you quoted yourself
...
directly contradicts this advice.


No it doesn't.

vector<MyObject>::iterator itor = vec.begin();
MyObject obj = (*itor);

or

vector<MyObject*>::iterator itor = vec.begin();
MyObject* obj = (*itor);


By dereferencing, you are working with the type you specifically wanted the vector to hold (which imo is clearer and easier to understand), not something else, which may be of a different type depending on many different things. Sorry if my initial statement didn't make my meaning clear.

Quote:
Original post by SiCrane
and using this information is quite often useful in writing efficient STL code


This I do not doubt, but sometimes readability and clearness take precedent over efficiency, especially for people new to STL. As the saying always goes, you can optimise later.


I have seen people banging their head against the wall due to

static_cast<SomeOtherObject*>( myItor );

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by SpreeTree
By dereferencing, you are working with the type you specifically wanted the vector to hold (which imo is clearer and easier to understand), not something else, which may be of a different type depending on many different things. Sorry if my initial statement didn't make my meaning clear.

Your initial statement, "you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer", which you conveniently edited out of the quote, has nothing to do with that. What you just said is a restatement of your container of pointers argument, my objection to which you didn't address.

Quote:

This I do not doubt, but sometimes readability and clearness take precedent over efficiency, especially for people new to STL. As the saying always goes, you can optimise later.

And using those facts are also useful in writing more readable and clear code. Unless you think that

std::vector<MyObject> temp = my_vector.begin();
std::advance(temp, 7);
do_something(temp)

is more clear and readable than

do_something(my_vector.begin() + 7)

Quote:

I have seen people banging their head against the wall due to

static_cast<SomeOtherObject*>( myItor );

And this code shows no mention of operator -> whatsoever.

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by SiCrane
Your initial statement, "you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer", which you conveniently edited out of the quote, has nothing to do with that. What you just said is a restatement of your container of pointers argument, my objection to which you didn't address.


I'm sorry, but I didn't 'conveniently edit' something to try and make my point I simply wanted to cut down on the amount of quoting. Maybe I'm not explaining myself clearly enough.

I was trying to stress that if you start to believe that an iterator is a pointer (which using -> can lead you to think that especially when you start to use STL), then it will cause you problems in the future. I don't know if "you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer" was clear enough, but I meant you can save yourself time by knowing exactly why treating an iterator like a pointer causes errors, rather then trying to use it as one and not knowing why it doesn't work.

By dereferencing the iterator, you are working with the basic type stored within the vector, a type you know and a type you understand.

Would I dereference a vector<MyObject**>::iterator. To right I would. I'd much rather use the basic type (MyObject**) as I assume I know what that is, know how it works and understand the context in which I am using it.

Quote:
Original post by SiCrane
And using those facts are also useful in writing more readable and clear code. Unless you think that
... Some STL Code...


No, but then that example doesn't cover the concerns I was having. Both versions treat the iterator as a MyObject*.

Personally I would call do_something(*(my_vector.begin()+7)) and pass it by reference for two reasons
* I don't want it passed by pointer because I don't want to treat an iterator as such
* I'm taking it that it cannot be null (and if it was out of bounds, then iterator debugging would hopefully catch it).


Quote:
Original post by SiCrane
And this code shows no mention of operator -> whatsoever.


I'm not sure what you are trying to prove with that statement because of course it doesn't. But by being able to use iterators as pointers (by being able to use operator->), people do think they can treat them as they would any kind of pointer, hence the example of a cast (which it trying to show a case in point where not treating iterators as pointers can save you time).


We are talking about two different things here. You are talking about the implementation details of the STL, I'm specifically talking about the use (and specifically the ease of use) of the STL. Knowledge of the STL is not something that everyone has, and I can assure you iterators are one of the things that tend to trip people up. By keeping it within the realms that people are confident with, that makes the intent clear (something which the STL often does not do), makes it easier to use and maintain, and makes it easier to move onto other concepts of the STL as your knowledge grows.

Whether you agree or not, I know this from experience.

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by SpreeTree
I don't know if "you can save a lot of time in the future when you start trying to treat an iterator as you would a pointer" was clear enough, but I meant you can save yourself time by knowing exactly why treating an iterator like a pointer causes errors, rather then trying to use it as one and not knowing why it doesn't work.

Considering that the statement has nothing to do with what you say it means, then it probably isn't clear enough. Re-read that sentence a few times. You said that using treating an iterator like a pointer saves time, which, as I said, contradicts your argument. It says nothing about understanding why treating an iterator as a pointer would cause errors. It instead says that treating an iterator as a pointer is beneficial.

Quote:
Would I dereference a vector<MyObject**>::iterator. To right I would. I'd much rather use the basic type (MyObject**) as I assume I know what that is, know how it works and understand the context in which I am using it.

Not what I asked, especially given that using -> on a vector<MyObject **>::iterator would be invalid. I asked if you would always dereference normal pointers, since that makes your code that uses double pointers the same as the code that uses normal pointers. Since you think that the existence of vector<MyObject*>::iterator justifies always dereferencing vector<MyObject>::iterators before using them, applying the same logic to pointers means that you would never use -> on a MyObject * since you can't use -> on a MyObject **.

Quote:

Personally I would call do_something(*(my_vector.begin()+7)) and pass it by reference for two reasons

But you're still doing random access iterator arithmetic on the iterator, which is something you can do on normal pointers, which by your logic makes you think of iterators like pointers, so you should never do.

Quote:
But by being able to use iterators as pointers (by being able to use operator->),

Using -> isn't using an iterator as a pointer, it's using an iterator as an iterator.

Unless you want to say that any valid operation on an iterator that is also a valid operation on a pointer is using an iterator like a pointer. In which case there is absolutely no operation on an iterator that isn't also using an iterator as a pointer. Even dereferencing an iterator like you suggest would be using an iterator like a pointer.

Quote:
You are talking about the implementation details of the STL,

And where do you see any implementation details in my posts? I'm talking about the use of STL, and the inconsistency of your arguments for not using iterator functionality. A brief perusal of this thread shows the only implementation detail mentioned would actually have been brought up by you, with your alleged STL implementation that doesn't support -> on container iterators.

Share this post


Link to post
Share on other sites
SpreeTree    396
Quote:
Original post by SiCrane
Considering that the statement has nothing to do with what you say it means, then it probably isn't clear enough. Re-read that sentence a few times. You said that using treating an iterator like a pointer saves time, which, as I said, contradicts your argument.


While I can accept the sentence could have been taken further (to detail exactly what I meant), I think I have cleared that up though but for some reason you don't seem happy with that (to try and make that obvious, I have edited the original post).


Quote:
Original post by SiCrane
Not what I asked


Okay, to answer what you actually asked (I think we are both misunderstanding each other here), no I wouldn't, but I am specifically talking about the use of iterators. Raw pointers declared as raw pointers are totally different, and I can't belive you are using that as an argument.


Quote:
Original post by SiCrane
Since you think that the existence of vector<MyObject*>::iterator justifies always dereferencing vector<MyObject>::iterators before using them, applying the same logic to pointers means that you would never use -> on a MyObject * since you can't use -> on a MyObject **.


Using that as justification is not what I have been doing at all, I used it as an example of consistency. For consistency (and clarity), in my example you are always using the base type. To use the iterators as they come, you need to know that vector<MyObject*>::iterator is a MyObject**. Many people have issues with pointers as it is, let alone them having to use **.


Quote:
Original post by SiCrane
But you're still doing random access iterator arithmetic on the iterator, which is something you can do on normal pointers, which by your logic makes you think of iterators like pointers, so you should never do.


I can also use operator+ on integers, but that doesn't make me think iterators are ints does it. Using operator-> is a more specific case that most people will use specifically for pointers, and that is the point I am trying to make.

I would also expect someone with less experience of the STL (which is the people I am specifically talking about) to use my_vector[7], which returns a reference anyway.


Quote:
Original post by SiCrane
Even dereferencing an iterator like you suggest would be using an iterator like a pointer.


Indeed, and in some cases I would say that was a mis-design on the part of the STL specification. It would be nice to have an option of dereferencing an iterator using an STL specific operation, rather than operator*. I am saying that being able to use ALL pointer operators on iterators can lead down a rough road, which it can.

Quote:
Original post by SiCrane
with your alleged STL implementation that doesn't support -> on container iterators.


Alleged... You're obviously not going to be happy with any explanation I make on this one, but hey, that’s how it is.


I'm sorry you keep saying my arguments are not consistent, but I have said the same thing in many different ways, taking it from a specific outlook (that of the inexperienced user of STL). Personally I think you are picking holes in an argument that isn't there. I fully understand that iterators can be used like pointers, I just don't agree that in all cases they should be. Unfortunately, you don't seem to want to see where I am coming from regardless of how it put it - and this could go on all night, which I rather it didn't :)

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by SpreeTree
Okay, to answer what you actually asked (I think we are both misunderstanding each other here), no I wouldn't, but I am specifically talking about the use of iterators. Raw pointers declared as raw pointers are totally different, and I can't belive you are using that as an argument.

Totally different? Iterators share the exact same syntax, because that's how iterators are designed.

Quote:
Using that as justification is not what I have been doing at all, I used it as an example of consistency.

No, that's one of the things you listed as one of your justifications. You even quoted yourself on it:
Quote:

getting into a habit of dereferencing an iterator makes it easier to use things like vector<MyObject*>::iterator, as you then have a more consistent code base when it comes to the STL.

Remember that post where you quoted yourself three times and said those were the three reasons you think you should always dereference iterators? It wasn't that long ago.

Quote:
For consistency (and clarity), in my example you are always using the base type. To use the iterators as they come, you need to know that vector<MyObject*>::iterator is a MyObject**. Many people have issues with pointers as it is, let alone them having to use **.

So why not for consistency (and clarity) would you not always use the base type of the pointer? Since you think pointers are so difficult then why do you think that you shouldn't always dereference a normal pointer to create a more consistent code base when it comes to pointers? You seem to think iterators are so difficult it's important to create a consistent code base when it comes to iterators.

Quote:
Original post by SiCrane
Using operator-> is a more specific case that most people will use specifically for pointers, and that is the point I am trying to make.

So would you also tell people to always dereference a boost::shared_ptr<> or a std::auto_ptr<> before using them? After all, both of them use operator -> and you can't static_cast either of those to a pointer type either.

Quote:
I would also expect someone with less experience of the STL (which is the people I am specifically talking about) to use my_vector[7], which returns a reference anyway.

And it wouldn't compile with a function that accepts either a pointer or iterator, so I fail to see how pointer/iterator confusion would apply here.

Quote:
Indeed, and in some cases I would say that was a mis-design on the part of the STL specification. It would be nice to have an option of dereferencing an iterator using an STL specific operation, rather than operator*.

You have that option:

template <typename T>
typename std::iterator_traits<T>::value_type STL_dereference(T iter) {
return *iter;
}



Quote:
Alleged... You're obviously not going to be happy with any explanation I make on this one, but hey, that’s how it is.

Any iterator class that has a functioning operator*, has a one liner implementation of operator-> : return &**this;. The chances of anyone managing to screw this up, and still produce anything even in the neighborhood of an otherwise functional STL implementation, are so low as to be laughable. Compare that to the probability that someone who doesn't seem like they really know what they're talking about making up an fictional non-compliant STL implementation that supports their argument while at the same time being conveniently unmentionable due to NDA.... So yes, alleged.

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by SpreeTree
... using is [*it, operator->] can lead people to believe that vector<>::iterator is a pointer when in-fact it is not.

... except when it is, as has been done, as pointers are legitimate iterators and vector's contiguity allows them to suffice.

I'll make it short: It's my experience that f( a->b->c, d->e->f ) is clearer than f( (*(*a).b).c, (*(*d).e).f ), having spent insufficient time playing with Matryoshka Dolls or LISP to sufficiently damage by brain.

Given the cost to readability, I'd much rather:
1) Give my fellow coder a clue (pointers are iterators, and that's not hard to explain!)
2) Submit the 1-liner bug fix (for those iterators missing the required operator->s!)
3) Completely ignore the addled reasoning behind arbitrary distinctions between pointers and other random access iterators and their ancestors and "Pretend" that pointers are just another iterator type.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this