Archived

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

aaron_ds

Member aliases

Recommended Posts

I have a point class that I use to store three floats in (x,y,z). However, I would also like to be able to call them by different names for instance (a,b,c) or (r,g,b). Is this impossible using C++ or am I just missing something obvious? Thank you

Share this post


Link to post
Share on other sites
It''s not standard and probably not good practice, but you can do something like with MSVC:

class Point {
public:
union {
struct {
float x;
float y;
float z;
};
struct {
float a;
float b;
float c;
};
struct {
float r;
float g;
float b;
};
};
};

Share this post


Link to post
Share on other sites
I want to use the class for a variety of situations. Otherwise, I would have 3 classes with the only difference between them being the names of the members.

Share this post


Link to post
Share on other sites
quote:
Original post by aaron_ds
I want to use the class for a variety of situations. Otherwise, I would have 3 classes with the only difference between them being the names of the members.


This is probably not what you want to hear...

I don''t think that is a very good reason. There are many differences between a color and a point. The fact that their implementations are similar now is not a good reason for making them the same class. What happens when you start adding member functions? You are giving up a lot of flexibility for a tiny bit of convenience.

On the other hand, if all you are doing is creating a class that holds three floats, then it shouldn''t matter what they are named because the class is not a point and it is not a color, it is just something that holds three floats.

Share this post


Link to post
Share on other sites
Use references! Just have some public member references and point them to whatever you want at construction time.

Edit: However, I agree with the above poster.

[edited by - dcosborn on March 21, 2004 2:39:14 PM]

Share this post


Link to post
Share on other sites
Using references as member aliases is a bad idea. That will bloat the size of the class for no good reason. It also subverts const-correctness.

Share this post


Link to post
Share on other sites
I don''t understand how references subvert const correctness. If you need constant references, just make them constant. If you mean that non-const references can be made to point constant variables, then thats not really an issue since you can do the same sort of thing with const_cast if you want, but any sensible person would avoid such a thing.

As for code size, I''d hope that a compiler would optimize it away.

Share this post


Link to post
Share on other sites
Well, I Have added member functions, mst of them being operators. And I agree that it is not the right way to do things. (the reason why im asking). Perhaps inheritance would be a better solution? Have a generic class which holds 3 floats and then derive a point, etc from there? But that beingsup the question of renaming still. Can I alias inherited members?

Share this post


Link to post
Share on other sites
Yes indeed you can make aliases for inherited members using references. The question is, is that the best solution?

Share this post


Link to post
Share on other sites
quote:
Original post by dcosborn
I don''t understand how references subvert const correctness. If you need constant references, just make them constant. If you mean that non-const references can be made to point constant variables, then thats not really an issue since you can do the same sort of thing with const_cast if you want, but any sensible person would avoid such a thing.

As for code size, I''d hope that a compiler would optimize it away.

Consider for a moment this code:

struct A {
float x;
float y;
float z;
};

struct B {
B() : a(x), b(y), c(z) {}

float x;
float y;
float z;
float & a;
float & b;
float & c;

void assign_x(float v);
void assign_a(float v);
};

void B::assign_x(float v) { x = v; }
void B::assign_a(float v) { a = v; }

int main(int, char **) {
std::cout << "sizeof(A): " << sizeof(A) << std::endl;
std::cout << "sizeof(B): " << sizeof(B) << std::endl;

const B const_b;
const_b.a = 5.0;
//const_b.x = 5.0;


return 0;
}

When compiled an run with MSVC .NET 2003, in release mode with full optimization, sizeof(B) is twice the value of sizeof(A). Meaning data size is greater when using references.

When I take a look at the dissassembly for B::assign_a() versus B::assign_x() there''s see an extra mov instruction in the generated assembly code. Which means code size is greater.

What''s more alarming is that I was able to assign to the value of a const object, because the references are there adding a nasty layer of indirection. No warning message. No red-flag from a const_cast. Just a straight up alteration to a const object. I might also add that it also subborns the DFA pass that many compilers perform when doing code generation.

Share this post


Link to post
Share on other sites
Thanks for the informative post SiCrane. I wonder if its possible for compilers to evolve to the point of optimizing away the references. I don''t know much about compiler programming.

If we use const references to point to const data, there won''t be a problem with accidentally changing const data, right? I guess just be careful that you know what you''re doing when you make a reference to something.

If I were you aaron_ds, I would probably just make a primitive templated vector class and use that for all my points, velocities, and whatever else makes sense. I wouldn''t worry about inheriting for specific types. For access I''d use subscript operator ([]).

Share this post


Link to post
Share on other sites
Hrm, It looks like I''ve finally come to the limitations of the language, rather than my own
Thanks so much for the help. Its not critically important that I be able to access them this way, but it doesn''t make sense accessing certian data by x,y,z when mentally im thinking something else.

What got me started thinking about this, is the interchangeability of the ''member'' names in ASM style fragment programs: .xyzw, .rgba, etc. Its too bad there isnt a compiler-friendly way to do this in c++.

Share this post


Link to post
Share on other sites
What about simiply having multiple getters and setters for each float?

So internally them maybe known as, a,b,c
then you have functions:
getX();
getY();
getZ();
getR();
getG();
getB();

which return the approprite value, it means that you have multiple functions that do the same thing but if that makes the class eaiser for you to work with for you.

-----------------------------------------------------
Writer, Programer, Cook, I''m a Jack of all Trades
Current Design project
Chaos Factor Design Document

Share this post


Link to post
Share on other sites
FWIW, the anonymous union/struct method is a pretty common one in nVidia's code, but not quite for exactly the same reasons as the OP's.

For instance, it's rather common to see


struct Vec3
{
union
{
float pos[4];
struct
{
float x, y, z, w;
};
};
};


simply because sometimes it's nicer to access as an array, and other times component-wise.

edit: note that like SiCrane mentioned earlier, it is non-standard and in my example, probably (definitely) not portable.


[edited by - mfawcett on March 22, 2004 3:09:57 AM]

Share this post


Link to post
Share on other sites