Question

Is there a way to create alias for class/stuct filed in C++11 ? What I mean

I've got class

class Vector4
{
    public:
        float X,Y,Z,W;
}

I got an alias

typedef Vector4 Color;

Is there a way to create aliases for Vector4 X,Y,Z,W fields to work as Color R,G,B,A ?

Was it helpful?

Solution

Just define Vector4 like this, using anonymous unions (without anonymous structs, though they are a common extension).

typedef struct Vector4
{
    union{float X; float R;};
    union{float Y; float G;};
    union{float Z; float B;};
    union{float W; float A;};
} Vector4;
typedef Vector4 Color;

If you cannot redefine Vector4, you might instead just define a layout-compatible standard-layout class and use the dreaded reinterpret_cast.
That works because standard layout classes having layout-compatible members are compatible.

struct Color
{
    float R, G, B, A;
}

Standard quote:

A standard-layout class is a class that:
— has no non-static data members of type non-standard-layout class (or array of such types) or reference,
— has no virtual functions (10.3) and no virtual base classes (10.1),
— has the same access control (Clause 11) for all non-static data members,
— has no non-standard-layout base classes,
— either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
— has no base classes of the same type as the first non-static data member.

A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class.
A standard-layout union is a standard-layout class defined with the class-key union.

OTHER TIPS

You can create an alias for a member variable in the way like below:

template <class Base, class Type, Type Base::*field>
struct Field {
   operator Type () const { return  base->*field; }
   Field& operator = (const Type& v) { base->*field = v; return *this; }

   Base* base;
};

So, you can have Color type like this:

class Color {
   Vector4 v;
public:
   Color() : v{}, R{&v}, G{&v}, B{&v}, A{&v} {}
   Field<Vector4, float, &Vector4::X> R;
   Field<Vector4, float, &Vector4::Y> G;
   Field<Vector4, float, &Vector4::Z> B;
   Field<Vector4, float, &Vector4::W> A;
};

Of course this Color type is no longer simple alias to Vector4...

This should work.

class Vector4
{
    public:

        Vector4 : X(0), Y(0), Z(0), W(1), R(X), G(Y), B(Z), A(W) {}

        float X,Y,Z,W;
        float& R;
        float& G;
        float& B;
        float& A;
};

But then, you have to implement copy constructor and copy assignment operators that do the right thing.

A better alternative will be to access them through a member function.

class Vector4
{
    public:

        Vector4 : X(0), Y(0), Z(0), W(1){}

        float X,Y,Z,W;
        float& R() { return X ;}
        float& G() { return y ;}
        float& B() { return z ;}
        float& A() { return w ;}

        float const& R() const { return X ;}
        float const& G() const { return y ;}
        float const& B() const { return z ;}
        float const& A() const { return w ;}
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top