Search code examples
c++arrayscglobaldesignated-initializer

Iterable Designated Initializer Alternative in C++


In C99, a struct array can be initialized

 static struct {char* tag; char* msg;} help_info[] = {[0]={"tag0","msg0"}, [1]={"tag1", "msg1"}};

This is not valid in C++. What is a possible alternative to replicate this behavior for an iterable object containing defined information?


Solution

  • C++20 added designated initializers to C++. There are some restrictions compared to C, in a couple of different directions. In your case, the main difference of note is that C++ has tightened up a bit of the type system so you can no longer initialize a char * from a string literal.

    In C, you can initialize a char * from a string literal for the sake of backward compatibility, but you still have to treat it as if it were a char const *--that is, if you try to write to the string literal you get undefined behavior (and on a modern machine, you'll typically get something on the order of a seg fault that will kill your program).

    C++ now demands that you recognize that limitation by using char const * explicitly. If we change your code to suit:

    static struct {char const* tag; char const* msg;} help_info[] = 
         {[0]={"tag0","msg0"}, [1]={"tag1", "msg1"}};
    

    ...and compile it as C++, it's perfectly fine.

    Do note there are other limitations that don't exist in C (but they don't affect this code). For example, C++ demands that the initializers be in order, so in C you also do this:

    static struct {char const* tag; char const* msg;} help_info[] = 
         {[1]={"tag1", "msg1"}, [0]={"tag0","msg0"}};
    

    ...so the initializer for [1] precedes the initializer for [0], but in C++ that's forbidden.