[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 Jens Maurer changed: What|Removed |Added CC||jens.maurer at gmx dot net --- Comment #12 from Jens Maurer --- In general, we want to be rather careful that the layout of the non-static data members of a class cannot depend on properties of other non-static data members that are visible due to some "complete class" rules. Otherwise, it's way too easy to construct cycles.
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #11 from Stas Sergeev --- So if I understand correctly, before your proposal the following code was conforming: template struct B { static constexpr int off = O(); }; struct A { char a; B<[]() static constexpr ->int { return offsetof(A, b); }> b; }; due to 7.1 (function body) + note4 for closure sub-class. Do you know any specific reason why that code should be disallowed, rather than supported per the current standard? After reinterpret_cast is constexpr was also disallowed, it became quite challenging to come up with the work-around.
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #10 from Stas Sergeev --- OMG, not what I intended to get. :( All I need is to use offsetof() in templates. Last time I started to use reinterpret_cast for that, you disallowed reinterpret_cast in constexpr context. Now this... Why is it such a big deal to disallow every possible loop-hole for the use of offsetof() in templates?
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #9 from Richard Smith --- I don't think we intended for default arguments of class-scope lambdas to get the same complete-class context treatment as default argument of member functions, but the standard wording does currently seem to suggest that they do get that treatment. Filed https://github.com/cplusplus/CWG/issues/449 to suggest the standard wording be fixed to match the implementations.
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #8 from Stas Sergeev --- Added a few experts who can probably answer that. While I do not doubt that Andrew is right, I am sure having the properly spelled explanation will help.
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #7 from Stas Sergeev --- Also I verified your assumption in comment #5 by this code: struct A { struct dummy { static constexpr const int foo(const int off = offsetof(A, a)) { return off; } static constexpr const int operator()() { return foo(); } }; static constexpr const int (*off_p)() = ::operator(); int t[off_p()]; char a; }; It says: error: size of array ‘t’ is not an integral constant-expression 11 | int t[off_p()]; So it seems, "constexpr const" is not enough to alter the structure size, so your fears about that were likely wrong. So could you please explain why note4 doesn't apply to the nested closure type? Unless there is a consistent explanation, the chances are that the bug is missed. :(
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #6 from Stas Sergeev --- (In reply to Andrew Pinski from comment #5) > Nope, lamdba's are not a nested class. But according to this: https://timsong-cpp.github.io/cppwp/n3337/expr.prim.lambda#3 The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below. This class type is not an aggregate ([dcl.init.aggr]). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. So am I right that defining lambda in class A, means defining it in a class's scope? In which case note4 should apply? What am I missing? Additionally I've got this to compile: struct A { struct dummy { static constexpr int foo(int off = offsetof(A, a)) { return off; } static constexpr int operator()() { return foo(); } }; static constexpr int (*off_p)() = ::operator(); int x; char a; }; Seems like note4 applies in that case. But it should be very similar to the "closure type" described above...
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #5 from Andrew Pinski --- (In reply to Stas Sergeev from comment #4) > (In reply to Andrew Pinski from comment #3) > > One more note, default argument clause does not apply here as the it is not > > an argument of a method of that class but rather a different context (the > > lamdba definition context). > > Yes, but doesn't this apply to the note4? > [Note 4: A complete-class context of a nested class is also a complete-class > context of any enclosing class, if the nested class is defined within the > member-specification of the enclosing class. > — end note] > > Isn't lambda an instance of a nested class here? Nope, lamdba's are not a nested class. > > > int off_p = offsetof(A, a); > > is well formed due to it being a DMI. > > Thanks for info. > Do you happen to know the particular reason > why the standard disallows this for static > member? Shouldn't that be a DR? Considering all compilers agree, it is not usually a defect report. I also don't see how this would work in really because you could use a `static constexpr` as an size for an array. That is: ``` #include struct A { static constexpr int (*off_p)(int p) = [](int off = offsetof(A, a)) { return off; }; int t[off_p(1)]; char a; }; ```
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #4 from Stas Sergeev --- (In reply to Andrew Pinski from comment #3) > One more note, default argument clause does not apply here as the it is not > an argument of a method of that class but rather a different context (the > lamdba definition context). Yes, but doesn't this apply to the note4? [Note 4: A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within the member-specification of the enclosing class. — end note] Isn't lambda an instance of a nested class here? > int off_p = offsetof(A, a); > is well formed due to it being a DMI. Thanks for info. Do you happen to know the particular reason why the standard disallows this for static member? Shouldn't that be a DR?
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #3 from Andrew Pinski --- One more note, default argument clause does not apply here as the it is not an argument of a method of that class but rather a different context (the lamdba definition context).
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 Andrew Pinski changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #2 from Andrew Pinski --- For the non-static case, "default member initializer" applies. That is: ``` #include struct A { char a; static constexpr int off_p = offsetof(A, a); }; ``` is illformed too. But ``` #include struct A { char a; int off_p = offsetof(A, a); }; ``` is well formed due to it being a DMI.
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #1 from Andrew Pinski --- clang rejects it for the same reason ... So does MSVC .