c++language-lawyerc++20structured-bindingsconstinit

Structured binding declaration cannot be `constinit`


Can one declare a structured binding with constinit specifier starting from C++20?

For example

struct A { int i, j; };

constinit auto [x, y] = A{ 0, 1 };

Here compilers somewhat diverge. MSVC complains:

error C3694: a structured binding declaration can contain no specifiers other than 'static', 'thread_local', 'auto', and cv-qualifiers

Clang follows it with the

error: decomposition declaration cannot be declared 'constinit'

But GCC just accepts the example. Online demo: https://gcc.godbolt.org/z/jaY7ncsPP

Which implementation is correct here?


Solution

  • Per [dcl.constinit]/1:

    The constinit specifier shall be applied only to a declaration of a variable with static or thread storage duration.

    A structured binding declaration is not a variable declaration.

    Also note that the same applies to constexpr as well. For constexpr GCC does also behave in line with the other compilers and rejects the declaration.


    As mentioned by Jonathan Wakely here, there is no specific problem with allowing constexpr (and presumably by extension constinit) on a structured binding, but there were open questions to the interpretation that delayed adding it to the standard.

    Work on this seems to be ongoing here. From what I can gather the goal is to make constexpr structured bindings not only enforce constexpr on the implicit variable definition, but also to make the structured bindings themselves usable in constant expressions, even if the variable has automatic storage duration.

    The latest revisions of that paper also handles constinit for structured bindings and would make your code well-defined with the expected behavior, i.e. that constinit will force the implicit variable definition implied by the structured binding declaration to be marked constinit, so that it must not have dynamic initialization.