Yeah, agreed; I'd really like to avoid any design that requires us to defer these decisions to the end of the TU; I suspect we'll find that brittle and with tough corner cases (not to mention the implementation complexity).
I guess it isn't even the dereference that's the problem, but the value-to-rvalue conversation on the resulting lvalue, right? If so, I think that would be okay: such an lvalue-to-rvalue conversion would still be immediate-escalating by virtue of being an expression of consteval-only type ([expr.const]/24.3), which coincides with when a complete type would be required. What do you think? (I did see the CWG issue; thanks for opening! I sometimes like to discuss these things a bit off-thread before engaging Core, just to get my thoughts together) On Mon, Jan 19, 2026, 10:11 AM Jakub Jelinek <[email protected]> wrote: > On Mon, Jan 19, 2026 at 09:42:05AM -0500, Daniel Katz wrote: > > Thanks for raising this issue, Jakub. > > > > I'm going to circle back with my coauthors regarding rationale for > > extending consteval-only-ness to pointers and references. > > > > If such types weren't consteval-only, do you think that would be > sufficient > > to solve the issue? Any concerns that come to mind with that approach > > (e.g., ways that it would allow meta::info to leak to anytime)? > > I've filed https://github.com/cplusplus/CWG/issues/836 so it can be > discussed further there (though perhaps I should have included there more > details). > If e.g. pointers to consteval-only aren't consteval-only (or perhaps they > are treated that way from within class non-static data members but not > otherwise), then the question is how to arrange after > struct A; > A *p; > struct A { std::meta::info a; }; > not emitting runtime code which dereferences *p, it is fine to emit such a > pointer into the compiled code, it has well defined size etc. But one > better wouldn't dereference such pointer (which it can't be dereferenced > before the class is complete, and can't be dereferenced in constant > evaluated code because the var is not constexpr). > From the implementation POV, I think it would be easier if we could decide > if a class is consteval-only or not at the class definition time rather > than > having to defer all the consteval-only related decisions until end of TU, > whether it is just non-static data members in there with consteval-only > class types / std::meta::info or pointers/references/array/function types > to those too (for references I guess the referenced type > needs to be complete at least in the NSDMs, but in function types one can > have references to incomplete types: > struct S; > struct T { int (*p) (S &); }; > ). Though it would be really complicated if we had say consteval-only vs. > non-consteval-only pointers to the same class and had to treat them > differently (non-consteval-only e.g. ones parsed when the pointed type > was still incomplete and consteval-only when it was complete and determined > to be consteval-only). > > Jakub > >
