Please consider the program as follows. GCC correctly initializes struct A, but in more simple case of struct B it fails: ``` template<typename T, int N> struct A { T t[N]; }; template<typename T> struct B { T t[2]; }; int main() { A a{{1, 2}}; // ok in gcc B b{{1, 2}}; // error in gcc (ok in other compilers, e.g. msvc) return a.t[0]; } ``` I believe, struct B initialization shall work here same way.
N.B. the code requires -std=gnu++20 to compile. (In reply to Fedor Chelnokov from comment #0) > A a{{1, 2}}; // ok in gcc > B b{{1, 2}}; // error in gcc (ok in other compilers, e.g. msvc) FWIW MSVC seems to be the only compiler that accepts it. Clang and Intel do not accept either line, due to incomplete C++20 support.
Another rejects-valid example (I think): template<class T=void> struct C { int m; int t[2]; }; C b{1, {2, 3}}; The relevant wording seems to be https://eel.is/c++draft/over.match.class.deduct#1.5. Rather than only "considering" brace elision for int[2] (and other non-dependent aggregate type), we seem to require it.
We started rejecting the comment #2 example after r11-1615
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:be4a4fb516688d7cfe28a80a4aa333f4ecf0b518 commit r12-2991-gbe4a4fb516688d7cfe28a80a4aa333f4ecf0b518 Author: Patrick Palka <ppalka@redhat.com> Date: Wed Aug 18 08:37:45 2021 -0400 c++: aggregate CTAD and brace elision [PR101344] Here the problem is ultimately that collect_ctor_idx_types always recurses into an eligible sub-CONSTRUCTOR regardless of whether the corresponding pair of braces was elided in the original initializer. This causes us to reject some completely-braced forms of aggregate CTAD as in the first testcase below, because collect_ctor_idx_types effectively assumes that the original initializer is always minimally braced (and so the aggregate deduction candidate is given a function type that's incompatible with the original completely-braced initializer). In order to fix this, collect_ctor_idx_types needs to somehow know the shape of the original initializer when iterating over the reshaped initializer. To that end this patch makes reshape_init flag sub-ctors that were built to undo brace elision in the original ctor, so that collect_ctor_idx_types that determine whether to recurse into a sub-ctor by simply inspecting this flag. This happens to also fix PR101820, which is about aggregate CTAD using designated initializers, for much the same reasons. A curious case is the "intermediately-braced" initialization of 'e3' (which we reject) in the first testcase below. It seems to me we're behaving as specified here (according to [over.match.class.deduct]/1) because the initializer element x_1={1, 2, 3, 4} corresponds to the subobject e_1=E::t, hence the type T_1 of the first function parameter of the aggregate deduction candidate is T(&&)[2][2], but T can't be deduced from x_1 using this parameter type (as opposed to say T(&&)[4]). PR c++/101344 PR c++/101820 gcc/cp/ChangeLog: * cp-tree.h (CONSTRUCTOR_BRACES_ELIDED_P): Define. * decl.c (reshape_init_r): Set it. * pt.c (collect_ctor_idx_types): Recurse into a sub-CONSTRUCTOR iff CONSTRUCTOR_BRACES_ELIDED_P. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/class-deduction-aggr11.C: New test. * g++.dg/cpp2a/class-deduction-aggr12.C: New test.
Whoops, wrong PR number.. the above commit should refer to PR101803 not PR101820. I'll correct this tomorrow, after the ChangeLog entry is generated
The releases/gcc-11 branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:dc867191914eff2993312fc25c48db4b7c6289e9 commit r11-9079-gdc867191914eff2993312fc25c48db4b7c6289e9 Author: Patrick Palka <ppalka@redhat.com> Date: Wed Aug 18 08:37:45 2021 -0400 c++: aggregate CTAD and brace elision [PR101344] Here the problem is ultimately that collect_ctor_idx_types always recurses into an eligible sub-CONSTRUCTOR regardless of whether the corresponding pair of braces was elided in the original initializer. This causes us to reject some completely-braced forms of aggregate CTAD as in the first testcase below, because collect_ctor_idx_types effectively assumes that the original initializer is always minimally braced (and so the aggregate deduction candidate is given a function type that's incompatible with the original completely-braced initializer). In order to fix this, collect_ctor_idx_types needs to somehow know the shape of the original initializer when iterating over the reshaped initializer. To that end this patch makes reshape_init flag sub-ctors that were built to undo brace elision in the original ctor, so that collect_ctor_idx_types that determine whether to recurse into a sub-ctor by simply inspecting this flag. This happens to also fix PR101820, which is about aggregate CTAD using designated initializers, for much the same reasons. A curious case is the "intermediately-braced" initialization of 'e3' (which we reject) in the first testcase below. It seems to me we're behaving as specified here (according to [over.match.class.deduct]/1) because the initializer element x_1={1, 2, 3, 4} corresponds to the subobject e_1=E::t, hence the type T_1 of the first function parameter of the aggregate deduction candidate is T(&&)[2][2], but T can't be deduced from x_1 using this parameter type (as opposed to say T(&&)[4]). PR c++/101344 PR c++/101803 gcc/cp/ChangeLog: * cp-tree.h (CONSTRUCTOR_BRACES_ELIDED_P): Define. * decl.c (reshape_init_r): Set it. * pt.c (collect_ctor_idx_types): Recurse into a sub-CONSTRUCTOR iff CONSTRUCTOR_BRACES_ELIDED_P. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/class-deduction-aggr11.C: New test. * g++.dg/cpp2a/class-deduction-aggr12.C: New test. (cherry picked from commit be4a4fb516688d7cfe28a80a4aa333f4ecf0b518)
Fixed for GCC 11.3 and 12.
Thanks! Related discussion: https://stackoverflow.com/q/67280884/7325599