0

I want to define a lot of union like this:

union {
  float a;
  float b;
  float c;  // there can be many variables
} a;

i dont want to make code be too large

so i want to define a macro to slove this.

the ideal macro looks like:

#define U(real_name, ...)/
union {\
....

and i just need one line to define:

U(a, b, c, d)

but i dont know how to get the variadic element from ..., can you help on this?

timrau
  • 22,578
  • 4
  • 51
  • 64
nick
  • 832
  • 3
  • 12
  • 2
    Why do you need `union { float a; float b; float c; } a;`? Wouldn't `struct { float a; } a;` do basically the same job? – Caleth Jun 15 '21 at 08:09
  • I want assign the variable several names, so that i can reuse the struct for different data @Caleth – nick Jun 15 '21 at 08:12
  • 2
    "i can reuse the struct for different data" Names of data members do not need to be globally unique. It sounds like you fundamentally misunderstand what a `union` is – Caleth Jun 15 '21 at 08:17
  • Unions overlay their members at the same memory location. Only one single member can be active at the same point of time. `U(a, b, c, d)` is not meaningful in this respect. – Aconcagua Jun 15 '21 at 08:20
  • 1
    @Aconcagua i just want to use it to make my code more readable, for example, union have two member cat and dog, i want the readers can know what data i am using. – nick Jun 15 '21 at 08:24
  • Be aware that type punning via unions is undefined behaviour in C++ (other than in C). You might want to place a cat in there. Fine. But you need to keep track of what you have placed in there by *other* means. A better/safer alternative is [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant). – Aconcagua Jun 15 '21 at 08:28
  • If you are talking about cats and dogs, have you considered a polymorphic approach, dropping the union at all? `class Animal {}; class Cat : public Animal {}; class Dog : public Animal {}` – allowing to assign both cats and dogs to `Animal*` pointers (or references where better suited). – Aconcagua Jun 15 '21 at 08:46
  • Related to [is-it-possible-to-iterate-over-arguments-in-variadic-macros](https://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros) – Jarod42 Jun 15 '21 at 08:47
  • OK, right from the start: What do you *actually* want to achieve? It looks to me more and more like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Aconcagua Jun 15 '21 at 08:54

1 Answers1

1

Try this:

#define SIZEOF_VA_ARGS(...) SIZEOF_VA_ARGS_(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define SIZEOF_VA_ARGS_(_1, _2, _3, _4, _5, N, ...) N

#define U_1(type, memb)      type memb
#define U_2(type, memb, ...) type memb; U_1(type, __VA_ARGS__)
#define U_3(type, memb, ...) type memb; U_2(type, __VA_ARGS__)
#define U_4(type, memb, ...) type memb; U_3(type, __VA_ARGS__)
#define U_5(type, memb, ...) type memb; U_4(type, __VA_ARGS__)

#define CONCAT(a, b)  a##b
#define U_(N, type, ...) CONCAT(U_, N)(type, __VA_ARGS__)

#define U(...) \
    union { U_(SIZEOF_VA_ARGS(__VA_ARGS__), float, __VA_ARGS__); }
U(a, b, c, d) foo;
// or
using mytype = U(a, b, c, d);
mytype foo;

Note that the above code only supports a maximum of five members, so if you want to use more than five members, you will need to define U_6, U_7, ..., and insert numbers to the definition of SIZEOF_VA_ARGS/SIZEOF_VA_ARGS_.

kakkoko
  • 179
  • 10