0

Let us suggest I have a class called vec4. Its a template and could be uint8, float or int in most cases. Other cases are allowed but are less likely. The class looks like this:

template<class T>
class vec4 {
public:
    vec4(){}
    virtual ~vec4(){}

    union {
      struct {
        T x,y,z,w;
      };
      struct {
        T r,g,b,a;
      };
    };
};

This helps me think about a problem in different ways when writing code and allows me to do other cool things also and I rather enjoy the design pattern when ever applicable.

The problem is I would like to extend the class and add functions in the case it is a 32 bit float. That I can do. I would also like to extend the union for a further maths paradigm where the third members are T c,y,m,k.

I am finding it very difficult to find material on the subject. This code extends the template, allowing specialised functions however, I would also like to extend the union within.

template<>
class vec4<float> {
public:
    vec4(){}
    virtual ~vec4(){}
};

The following specialisation compiles but doesn't allow me to also access members as an x,y,z,w object though;

template<>
class vec4<float> {
public:
    vec4(){
        this->i=0;
        this->j=0;
        this->k=0;
        this->l=0;
    }
    vec4(float a){
        this->i = a;
        this->j = a;
        this->k = a;
        this->l = a;
    }

    union {
        struct {
            float i,j,k,l;
        };
    };
};

I was able to add this line:

struct vec4<float>;

to the specialized template. It would compile until trying to access the x,y,z,w members;

Patrick Sturm
  • 393
  • 1
  • 13
  • This is called template specialization. Although search engines will return plenty of links, for this keyword, search engines are not replacements for C++ textbooks, where you will find a complete description and a thorough explanation of advanced C++ topics, like this one. – Sam Varshavchik Jan 01 '23 at 00:43
  • Note that those uses of `struct` are not standard C or C++. They’re a Microsoft thing. – Pete Becker Jan 01 '23 at 01:10
  • I can't find any references however, to my requirement/desire to extend the union inside the class. Considering I can't reference the union outside the class I cannot fathom how this would look and searching far and wide is not helpful at all. Those structs are beautiful though. – Patrick Sturm Jan 01 '23 at 02:04
  • 1
    @PeteBecker What are you talking about? Looks pretty standard to me... – sklott Jan 01 '23 at 02:04
  • @sklott — those are “anonymous `structs`” (analogous to anonymous unions), with no struct tag (name) and no object name. Microsoft allows them as members of anonymous unions from the olden days of Windows programming. They’ve never been standard. See [here](https://stackoverflow.com/questions/2253878/why-does-c-disallow-anonymous-structs), for example. – Pete Becker Jan 01 '23 at 04:05
  • @PeteBecker I don't know about C, but C++ explicitly allows anonumous classes (that includes either `class`, `struct` or `uinon`). See 2nd definition of *class-head* here: https://eel.is/c++draft/class.pre#nt:class-name – sklott Jan 01 '23 at 04:16
  • @sklott —read the answer to the question I linked to. You can have an **unnamed** struct; `struct { int i: } obj:`, and you can then refer to `obj.i`. You can have a struct without an object: `struct x { int i:}:`. But you cannot write a struct without a name if you aren’t creating an object. `struct { int i: }:` just isn’t allowed. – Pete Becker Jan 01 '23 at 04:24
  • @PeteBecker Ok. Got it. Though I don't see anything in standard that explicitly prohibits it. I mean I understand that its useless to declare anonymous struct by itself, but where usage in `union` is disallowed? – sklott Jan 01 '23 at 04:28

1 Answers1

0

May be its possible without intoducing additional name in union, but I don't know how. But with additional name you can do it this way:

template<typename U>
struct ExtraMembers {};

template<class T>
class vec4 {
public:
    vec4(){}
    virtual ~vec4(){}

    union {
      struct {
        T x,y,z,w;
      };
      struct {
        T r,g,b,a;
      };
      ExtraMembers<T> extra;
    };
};

template<>
struct ExtraMembers<float> {float c, m, y, k;};

int main()
{
    vec4<int> a;
    vec4<float> d;
    // a.extra.c = 0; // Error: No member named 'c'
    d.extra.c = 0.;
}

Edit: You can also hide ExtraMembers in anonymous or named namespace, but I don't think its possible to make it internal to vec4.

sklott
  • 2,634
  • 6
  • 17
  • In this specific problem, ExtraMembers is specifically sized at 128bit and cannot be resized. It also has no use outside the floating point concept. And specifically, should not be used unless it is floating point. – Patrick Sturm Jan 01 '23 at 02:30
  • So? I don't understand what is your question or concern. `sizeof(ExtraMembers) == 16`. It can't be resized. It has members `c, m, y, k` only for `float` specialization. As for usage you should either specialize you functions accordingly or use `if constexpr`. – sklott Jan 01 '23 at 03:07
  • 1
    This use of anonymous structs is not legal. https://stackoverflow.com/questions/2253878/why-does-c-disallow-anonymous-structs. – Pete Becker Jan 01 '23 at 04:26