Designated Initializers in C++20

The C++20 standard also gives us another handy way to initialize data members. The new feature is called designated initializers, and it might be familiar to C programmers.

The basics

In basic C++20 form, you can write:

Type obj = { .designator = val, .designator { val2 }, ... };

For example:

struct Point { double x; double y; };
Point p { .x = 10.0, .y = 20.0 };

Designator points to a name of a non-static data member from our class, like .x or .y.

One of the main reasons to use this new kind of initialization is to increase readability.

This is easier to read:

struct Date {
    int year;
    int month;
    int day;
};

Date inFuture { .year = 2050, .month = 4, .day = 10 };

Than:

Date inFuture { 2050, 4, 10 };

In the case of the date class, it might be unclear what the order of days/month or month/days is. With designated initializers, it’s very easy to see the order.

Rules

The following rules apply to designated initializers:

  • Designated initializers work only for aggregate initialization, so they only support aggregate types.
  • Designators can only refer to non-static data members.
  • Designators in the initialization expression must have the same order of data members in a class declaration.
  • Not all data members must be specified in the expression.
  • You cannot mix regular initialization with designers.
  • There can only be one designator for a data member
  • You cannot nest designators.

For example, the following lines won’t compile:

struct Date {
    int year;
    int month;
    int day;

    static int mode;
};

Date d { .mode = 10; }             // error, mode is static!
Date d { .day = 1, .year = 2010 }; // error, out of order!
Date d { 2050, .month = 12 };      // error, mix!

Advantages of designated initialization

  • Readability: A designator points to the specific data member, so it’s impossible to make mistakes here.
  • Flexibility: You can skip some data members and rely on default values for others.
  • Compatibility with C: In C99, it’s popular to use a similar form of initialization (although even more relaxed). With the C++20 feature, it’s possible to have very similar code and share it.
  • Standardization: Some compilers, like GCC or Clang, already had some extensions for this feature, so it’s a natural step to enable it in all compilers.

Examples

Let’s take a look at some examples:

Get hands-on with 1200+ tech skills courses.