Date: Wed, 16 Feb 2022 11:16:14 -0500
On Tue, Feb 15, 2022 at 10:40 AM David Ledger via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Gday all!
>
> In generic contexts it can be desirable to inherit the constructors of a base class. Currently, this leads to broken code when the base class is an aggregate, as it is no longer possible to initialize the aggregate base's members.
>
>
> An example:
>
> ---
> struct A { A(int a, int b, int c){} };
>
> struct B { int a, b, c; };
>
> template <typename T>
> struct N : T { using T::T; };
>
> N<A> a{1, 2, 3}; // current: ok, inherits A::A
>
> N<B> b{1, 2, 3}; // current: error, no constructor to inherit(and `N<B>` is now, not an aggregate)
> // proposed: ok, elides the braces, and aggregate constructs
>
> N<B> c{.a = 1, .b = 2, .c = 3}; // current: error, designated initializers cannot be used with a non-aggregate type 'Bar'
> // proposed: ok, Foo's a, b, and c are initialized via the designated initalizers.
> ---
>
> Proposal is here:
> ---
> https://gitlab.com/Sepps/inheriting-aggregate-initialization
I would be in favor of allowing `using T::T` to be ignored in the
cases where `T` is an aggregate, but I wouldn't be in favor of giving
`using T::T;` special powers when `T` is an aggregate. That is, if you
have this:
```
struct C : public B {};
```
You can do `C c{1, 2, 3};`, but you can't do `C c{.a = 1, .b = 2, .c =
3};`. It should remain that way if C had `using B::B;` in its
definition.
If we want the latter to happen, it ought to be able to happen for
*all* aggregate inheritance, not just the ones where you have `using
T::T;` in it. Aggregate initialization is not calling a constructor,
and we don't want to have the inheriting constructors feature make
aggregate initialization work differently than it normally does.
<std-proposals_at_[hidden]> wrote:
>
> Gday all!
>
> In generic contexts it can be desirable to inherit the constructors of a base class. Currently, this leads to broken code when the base class is an aggregate, as it is no longer possible to initialize the aggregate base's members.
>
>
> An example:
>
> ---
> struct A { A(int a, int b, int c){} };
>
> struct B { int a, b, c; };
>
> template <typename T>
> struct N : T { using T::T; };
>
> N<A> a{1, 2, 3}; // current: ok, inherits A::A
>
> N<B> b{1, 2, 3}; // current: error, no constructor to inherit(and `N<B>` is now, not an aggregate)
> // proposed: ok, elides the braces, and aggregate constructs
>
> N<B> c{.a = 1, .b = 2, .c = 3}; // current: error, designated initializers cannot be used with a non-aggregate type 'Bar'
> // proposed: ok, Foo's a, b, and c are initialized via the designated initalizers.
> ---
>
> Proposal is here:
> ---
> https://gitlab.com/Sepps/inheriting-aggregate-initialization
I would be in favor of allowing `using T::T` to be ignored in the
cases where `T` is an aggregate, but I wouldn't be in favor of giving
`using T::T;` special powers when `T` is an aggregate. That is, if you
have this:
```
struct C : public B {};
```
You can do `C c{1, 2, 3};`, but you can't do `C c{.a = 1, .b = 2, .c =
3};`. It should remain that way if C had `using B::B;` in its
definition.
If we want the latter to happen, it ought to be able to happen for
*all* aggregate inheritance, not just the ones where you have `using
T::T;` in it. Aggregate initialization is not calling a constructor,
and we don't want to have the inheriting constructors feature make
aggregate initialization work differently than it normally does.
Received on 2022-02-16 16:16:27