Archived

This topic is now archived and is closed to further replies.

conversion operator question

This topic is 5591 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I wrote the following piece of code:
  

struct AStruct {
  float a, b, c, d;

  operator float*()
   {
   return &a;
   }
};

  
Question: is it guaranteed that a, b, c and d are always allocated contiguously, that is: if I need to pass in the four floats from AStruct to some function, can I be guaranteed that those four floats are precisely what will arrive there? Thanks, Crispy

Share this post


Link to post
Share on other sites
For the sample struct you have shown, yes the positions of the floats will be layout-compatible with the expectations of a function. However, this is an incredibly fragile assumption to make, and is dreadful practice all-round. A better way to achieve what you want would be to do something like this:


  
class AClass
{
public:
const float* getFloatBuffer() const
{
return &buf_[0];
}
private:
float buf_[4];
};


An even better way would be to not expose the implementation details of the class whatsoever, and make the function that requires access to go via a higher level of abstraction, such as an interface which conveys the desired semantics for interacting with objects of type AClass.

Share this post


Link to post
Share on other sites
That''s basically what I was going to do, but AClass is actually a vector struct which stores the x, y and z values. It''s been used intensively in my code so far, so changing the respecitve values to an array, would either mean revising a whole lot of code or introducing an incompatible, new vector struct. Besides, accessing a vector''s elements as vec.v[0], etc isn''t remotely as clear as accessing them as vec.x, etc... I think''s I''ll go with the fragile solution here - sometimes you just have to cross your fingers, I suppose.

Thanks for clearing it up, though,
Crispy

Share this post


Link to post
Share on other sites
quote:
Original post by Crispy
It''s been used intensively in my code so far, so changing the respecitve values to an array, would either mean revising a whole lot of code or introducing an incompatible, new vector struct.

Yes, that''s what happens when you expose object layouts to the external world. The rest of the world comes to rely on that layout, and the entire application can become very resistant to change. I''m working on something right now where a similar "harmless" decision made a few years ago is causing huge problems, and is going to take many many weeks to sort out. You shouldn''t let problems fester, as they only become worse.
quote:

Besides, accessing a vector''s elements as vec.v[0], etc isn''t remotely as clear as accessing them as vec.x, etc

So why the conversion operator?

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
So why the conversion operator?


For glVertex3fv(float * param);... This way I won''t have to write glVertex3f(float x, float y, float z); which seems like an awful waste of space (and looks ugly).

A comparison I thought of just now: when reading contents of a file into a struct, actually the very same process takes place, only in reverse. Hence, instead of


  
struct vec
{
float x, y, z;
};

void func()
{
vec v;
fread(&v, sizeof(vec), 1, stream);
}


should be:


  
struct vec
{
float x, y, z;
};

void func()
{
vec v;
fread(&v.x, sizeof(float), 1, stream);
fread(&v.y, sizeof(float), 1, stream);
fread(&v.z, sizeof(float), 1, stream);
}


The prior sample actually presents us with a similar assumption, in fact, a totally unsound one, but is (very) common in practice...

Just a justification for what I''m about to do...

Crispy

Share this post


Link to post
Share on other sites
Try an unnamed union:


  
struct AStruct
{
union
{
struct
{
float x, y, z;
};
float val[3];
};
}


Then you can use either:


  
AStruct myStruct;
myStruct.x = 0;
myStruct.y = 1;
myStruct.z = 34.2;
glVertex3fv( myStruct.val );


Karg

Share this post


Link to post
Share on other sites
quote:
Original post by Crispy
For glVertex3fv(float * param);... This way I won''t have to write glVertex3f(float x, float y, float z); which seems like an awful waste of space (and looks ugly).

Why not glVertex3fv(vec v);?
quote:

fread(&v, sizeof(vec), 1, stream);

Not good, as it only works for POD types. Admittedly, you have a POD type, but that might not always be the case.
quote:

fread(&v.x, sizeof(float), 1, stream);
fread(&v.y, sizeof(float), 1, stream);
fread(&v.z, sizeof(float), 1, stream);

Better, but serialisation should really be within the class, else you''re having to expose object internals to the entire world simply for fread to gain access.
quote:

The prior sample actually presents us with a similar assumption, in fact, a totally unsound one, but is (very) common in practice...

Just a justification for what I''m about to do...

An admission that it is unsound does not provide justification. However, what you do in your code is your business. Similarly, whether you want to take any notice of my advice or not is your choice, but bear in mind that I''ve seen this story unfold to its logical conclusion many times. The conclusion being that the code eventually ends up being such a mess that it is declared unfit for purpose, as it causes simple changes to consume an inordinate amount of time + effort.

Share this post


Link to post
Share on other sites