C++ Logo

SG7

Advanced search

Subject: Re: Incomplete types
From: Cleiton Santoia (cleitonsantoia_at_[hidden])
Date: 2020-11-02 22:40:23


Sorry, I made few mistakes, let me be more clear:
Can the reflexpr operator in #2 "see" members of class X before reflexpr
usage like decltype ?

consteval auto get_member_types(info classtype) {
    auto result = members_of(classtype); // #1 members_of can see
incomplete class members ?
    for (auto &info : result) {
        info = type_of(info);
// I suppose this line converts 'int X::*' to 'int'
    }
    return result;
};

struct X {
    int a;
    bool b;
    char c;
    // so far we have 3 members...
    std::variant< typename( get_member_types( reflexpr (X) ) ) > d; // #2
can reflexpr see previous 3 members ? ( goto #1 )
};

Is the type of d "variant<int, bool, char>" ? Is this illegal ?

Thanks

Em seg., 2 de nov. de 2020 às 17:05, Wyatt Childers via SG7 <
sg7_at_[hidden]> escreveu:

> I believe what you're thinking of is from within a fragment
> https://cppx.godbolt.org/z/bazc9K:
>
> class foo {
> consteval {
> -> fragment struct {
> foo bar() { // this isn't okay, foo is incomplete
> return {};
> }
> };
> }
> };
>
> You can of course express the same idea, however you need to do this
> indirectly (so that injection can sew things together for you, at the right
> time):
>
> class foo {
> consteval {
> -> fragment struct {
> typename |%{reflexpr(foo)}| bar() {
> return {};
> }
> };
> }
> };
>
> Also, consider injection into another context (e.g. inject foo
> global_bar() { return { }; } into the global namespace):
>
> class foo {
> consteval {
> -> namespace(::) fragment namespace {
> typename |%{reflexpr(foo)}| global_bar() {
> return {};
> }
> };
> }
> };
>
> This injection is delayed until the class is complete, and then injected
> into the global namespace -- allowing the compiler to work with this code
> "in the usual way".
> ------------------------------
>
> That means you can't rely on declarations assumed to have been injected
>
> template<typename T>
> struct my_class {
> consteval { -> inject_useful_decl<T>(); }
> decltype(useful_decl) var; // oops. error: no useful_decl declared.
> };
>
> Correct, this doesn't work, as the consteval block doesn't execute until
> the template is instantiated (https://cppx.godbolt.org/z/97v6Wr).
> ------------------------------
>
> I don't think we have to make consteval blocks part of the complete-class
> context of the enclosing class. Lookup already works. We just have to
> ensure that it is clear that some properties of nonstatic data members
> aren't queryable.
>
> struct S {
> int a;
> consteval {
> -> inject_useful_decl<typename(reflexpr(S::a))>(); // Okay.
> }
> consteval {
> -> inject_other<meta::offset_of(reflexpr(S::a))>(); // Error.
> }
> };
>
> A question we'd have to answer is whether a reflection of a nonstatic data
> member obtained while the class is still incomplete would remain valid
> after the class is completed, and, if so, whether the completeness would be
> reflected in that reflection (so that, e.g., querying the offset later on
> would work). IMO, the answer should be yes to both of those.
>
> Agreed, on all points.
> On 11/2/20 2:03 PM, Andrew Sutton via SG7 wrote:
>
>
>> Default member initializers are parsed in a complete-class-context",
>> essentially meaning the parsing is delayed until the closing } of the class.
>>
>>
>> Right, but Hana's two examples aren't in such contexts, and we permit
>> them anyway. Lookup succeeds, but some operations (like offsetof) aren't
>> permitted.
>>
>
> Wow. I am not reading well today.
>
> Adding consteval blocks to the complete-class-context might make lookups
>> work in metaprograms, but that also breaks this very simple model.
>>
>>
>> I don't think we have to make consteval blocks part of the complete-class
>> context of the enclosing class. Lookup already works. We just have to
>> ensure that it is clear that some properties of nonstatic data members
>> aren't queryable. E.g.:
>>
>> struct S {
>> int a;
>> consteval {
>> -> inject_useful_decl<typename(reflexpr(S::a))>(); // Okay.
>> }
>> consteval {
>> -> inject_other<meta::offset_of(reflexpr(S::a))>(); // Error.
>> }
>> };
>>
>> A question we'd have to answer is whether a reflection of a nonstatic
>> data member obtained while the class is still incomplete would remain valid
>> after the class is completed, and, if so, whether the completeness would be
>> reflected in that reflection (so that, e.g., querying the offset later on
>> would work). IMO, the answer should be yes to both of those.
>>
>
> I must be forgetting where lookup fails, but we've definitely run into
> issues requiring complete class types in *some* contexts. Wyatt can
> probably answer that question better than I can at this point.
>
>
>
> --
> SG7 mailing list
> SG7_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7
>



SG7 list run by sg7-owner@lists.isocpp.org

Older Archives on Google Groups