1

I'm porting some old code from C to C++ in Visual Studio 2010 and I came across this:

typedef struct OptionDef {
    const char *name;
    int flags;
    union {
        void *dst_ptr;
        int (*func_arg)(void *, const char *, const char *);
        size_t off;
    } u;
    const char *help;
    const char *argname;
} OptionDef;

static const OptionDef options[] = {
    { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
    ...

Which now fails with a syntax error. I've seen the response for Statically initialize anonymous union in C++ but overloading the constructors won't work because I'm setting up an array. Is there any other way of doing this (rather than just rewriting the code not to use a union)?

Update: I should have been more specific - the array contains different initialisers using all parts of the union:

static int is_full_screen;

    { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },

So just changing the order of the union won't help.

Community
  • 1
  • 1
parsley72
  • 8,449
  • 8
  • 65
  • 98

2 Answers2

1

C++ does not have the .member initialization syntax that C has.

You can use aggregate initialization with unions but only on the first member.

Thus, rewrite it with the one you want to set as the first member:

union {
    int (*func_arg)(void *, const char *, const char *);
    void *dst_ptr;
    size_t off;
} u;

static const OptionDef options[] = {
    { "x", HAS_ARG, { opt_width }, "force displayed width", "width" },

You could also give your struct a constructor - C++11 should allow you to use brace initializers.

Example:

struct foo {
    int flags;
    struct uwrap {
      uwrap(int (*func_arg)(void *, const char *, const char *))
      : func_arg(func_arg) {}
      uwrap(int off)
      : off(off) {}
      union {
          void *dst_ptr;
          int (*func_arg)(void *, const char *, const char *);
          int off;
      };
    } u;
};

int func(void *, const char *, const char *) {}

int main() {
    foo f[] = { { 1, {func}}, { 2, {0}} };
}

In C++03 you can do it with temporaries if the struct has a constructor:

foo f[] = { foo(1, func), foo(3, 0) };
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • The first idea won't work, see my updated question. But can I use a constructor within an array? I didn't think this was possible. – parsley72 Nov 30 '12 at 03:08
-1

Just do this:

static const OptionDef options[] = {
   { "x", HAS_ARG, {opt_width }, "force displayed width", "width" },
    ...
TieDad
  • 9,143
  • 5
  • 32
  • 58
  • Will that work without reordering the union? I thought only the first member was set. – parsley72 Nov 30 '12 at 03:11
  • Union is just a block of memory with biggest size of it's elements. How to explain data stored in the memory depends on you code. For example, you set {0} as the union, if your code is "u.dst_ptr" then the "0" is NULL of dst_ptr; if your code is "u.func_arg", then the "0" is NULL function pointer; if your code is "u.off", then "0" means the off var is 0. That's the difference between union and struc. – TieDad Nov 30 '12 at 03:20