0

There have been other posts regarding initialization of array of nested structs. However, following the given advice elsewhere in Stackoverflow and links to Aggregate Initialization are not helping me resolve an issue.

My context is that I am initializing a number of nested structs in the Vulkan graphics API.

However, in looking at other codes for explanation I ran across the following 'C' initialization (please note that I am adding the defined structs and the code in question)

Vulkan typedefs

typedef union VkClearColorValue {
    float       float32[4];
    int32_t     int32[4];
    uint32_t    uint32[4];
} VkClearColorValue;

typedef struct VkClearDepthStencilValue {
    float       depth;
    uint32_t    stencil;
} VkClearDepthStencilValue;

typedef union VkClearValue {
    VkClearColorValue           color;
    VkClearDepthStencilValue    depthStencil;
} VkClearValue;

The 'C' code in question

    const VkClearValue clear_values[2] = {
            [0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
            [1] = {.depthStencil = {demo->depthStencil, 0}},
    };

The 'C' represenation is legal in C99 and the latest gcc compiler.

However, as I apply this to C++ I get errors.

Going back to rules for aggregate initialization the 'C' represenation should be legal in C++17. However, on compilation I get errors to the effect: error: expected primary-expression before '.' token

Clearly I am wrong in my assumption. As such, might anyone provide guidance on how to make it legal in C++17.

2 Answers 2

1

Going back to rules for aggregate initialization the 'C' represenation should be legal in C++17

You assume wrongly, as you have correctly concluded. C++ has had aggregate initialisation since the first standard version, but it doesn't support all initialisations that were added in C99. For example, designated initialisers are not in C++17 at all.

As such, trivial unions can only be initialised with the first member active, like in C89. To activate another member, it must be assigned after initialisation. To do this with a const object, you can use a function.


C++20 adds designated initialisers, but even then only subset of C is allowed. Following is well-formed in C++20:

const VkClearValue clear_values[2] = {
    {.color {.float32 = {0.2f, 0.2f, 0.2f, 0.2f}}},
    {.depthStencil = {42, 0}},
};
Sign up to request clarification or add additional context in comments.

Comments

0

This is not a valid form of aggregate initialization in c++, even though it is in c. In fact, there is a note:

Note: out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in the C programming language, but are not allowed in C++.

struct A { int x, y; };
struct B { struct A a; };
struct A a = {.y = 1, .x = 2}; // valid C, invalid C++ (out of order)
int arr[3] = {[1] = 5};        // valid C, invalid C++ (array)
struct B b = {.a.x = 0};       // valid C, invalid C++ (nested)
struct A a = {.x = 1, 2};      // valid C, invalid C++ (mixed)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.