Date: Mon, 2 Nov 2020 20:11:43 -0500
> Date: Mon, 2 Nov 2020 11:00:36 -0500
> From: Andrew Sutton <asutton.list_at_[hidden]>
> To: Hana Dus?kov? <hanicka_at_[hidden]>
> Cc: sg7_at_[hidden]
> Subject: Re: [SG7] Incomplete types
> Message-ID:
> <CAFVAEf1EJ6xFxJKD0OVd_OWRaoLGQA+30eL6LAnQ0u5XGvcuNQ_at_[hidden]>
> Content-Type: text/plain; charset="utf-8"
>
>> This seems counterintuitive to me. I consider `sizeof` and `decltype` a
>> poor version of a reflection and you can do this:
>>
>> struct X {
>>
>> int a;
>> static constexpr unsigned size = sizeof(X::a);
>> using type = decltype(X::a);
>>
>> };
>>
>> https://compiler-explorer.com/z/9f7WKn
>>
>> Even when the type is not yet complete. I personally think we should
>> support such cases.
>>
>
> Default member initializers are parsed in a complete-class-context",
> essentially meaning the parsing is delayed until the closing } of the
> class. This is why lookup works in those cases. The same is true of default
> arguments, inline member function bodies, and noexcept-specifiers.
>
> My mental model of injection via conseval blocks is very simple. First,
> consteval blocks have the guarantee that they are executed where they
> appear or where they're instantiated if they appear in a template. After
> the metaprogram runs, the compiler effectively "pastes" the injected code
> over top of the metaprogram as if you had manually typed in. Of course,
> whatever rules and restrictions apply to hand-written code also apply to
> metaprograms.
This is a good point to consider on its own. While I agree with the mental model that injection should result in "pasting" the contents into the enclosing context, given the different late-parsing behavior you describe, a user would get the following behavior, which probably won’t quite seem like pasting:
https://cppx.godbolt.org/z/rd6KT6
Perhaps a better way to put it is that model is that an executing metaprogram is just like *parsing* the contained declarations into the enclosed context, after resolving any dependencies. Parsing into a class does two things: 1. adds the essential content of the declarations immediately, and 2. defers parsing of the non-essentials until the closing brace of the outermost enclosing class. Evaluation of a metaprogram should probably result in both distinct effects as well.
> From: Andrew Sutton <asutton.list_at_[hidden]>
> To: Hana Dus?kov? <hanicka_at_[hidden]>
> Cc: sg7_at_[hidden]
> Subject: Re: [SG7] Incomplete types
> Message-ID:
> <CAFVAEf1EJ6xFxJKD0OVd_OWRaoLGQA+30eL6LAnQ0u5XGvcuNQ_at_[hidden]>
> Content-Type: text/plain; charset="utf-8"
>
>> This seems counterintuitive to me. I consider `sizeof` and `decltype` a
>> poor version of a reflection and you can do this:
>>
>> struct X {
>>
>> int a;
>> static constexpr unsigned size = sizeof(X::a);
>> using type = decltype(X::a);
>>
>> };
>>
>> https://compiler-explorer.com/z/9f7WKn
>>
>> Even when the type is not yet complete. I personally think we should
>> support such cases.
>>
>
> Default member initializers are parsed in a complete-class-context",
> essentially meaning the parsing is delayed until the closing } of the
> class. This is why lookup works in those cases. The same is true of default
> arguments, inline member function bodies, and noexcept-specifiers.
>
> My mental model of injection via conseval blocks is very simple. First,
> consteval blocks have the guarantee that they are executed where they
> appear or where they're instantiated if they appear in a template. After
> the metaprogram runs, the compiler effectively "pastes" the injected code
> over top of the metaprogram as if you had manually typed in. Of course,
> whatever rules and restrictions apply to hand-written code also apply to
> metaprograms.
This is a good point to consider on its own. While I agree with the mental model that injection should result in "pasting" the contents into the enclosing context, given the different late-parsing behavior you describe, a user would get the following behavior, which probably won’t quite seem like pasting:
https://cppx.godbolt.org/z/rd6KT6
Perhaps a better way to put it is that model is that an executing metaprogram is just like *parsing* the contained declarations into the enclosed context, after resolving any dependencies. Parsing into a class does two things: 1. adds the essential content of the declarations immediately, and 2. defers parsing of the non-essentials until the closing brace of the outermost enclosing class. Evaluation of a metaprogram should probably result in both distinct effects as well.
Received on 2020-11-02 19:11:48