Title
Incomplete consteval-only class types
Status
drafting
Section
6.9.1 [basic.types.general]
Submitter
Jakub Jelinek

Created on 2026-01-19.00:00:00 last changed 3 days ago

Messages

Date: 2026-03-01.21:55:49

Suggested resolution:

  1. Change in 6.9.1 [basic.types.general] paragraph 12 and split into separate paragraphs as follows:

    A type is consteval-only if it is
    • std::meta::info,
    • cv T, pointer to T, reference to T, or array of T, where T is a consteval-only type,
    • a pointer or reference to a consteval-only type,
    • an array of consteval-only type,
    • a function type having a return type or any parameter type that is consteval-only,
    • a class type with any a non-static data member having of consteval-only type, or
    • a type “pointer to member of class C of type T”, where at least one of C or T is a consteval-only type.
    A type is observably consteval-only from a program point P if it is
    • std::meta::info,
    • cv T, pointer to T, reference to T, or an array of T, where T is observably consteval-only from P,
    • a function type having return type or any parameter type that is observably consteval-only from P,
    • a class type that is complete from P with a non-static data member whose type is observably consteval-only from P, or
    • a type "pointer to member of class C of type T", where at least one of C or T is observably consteval-only from P.

    [ Note: Every type which is observably consteval-only from some program point is also consteval-only. --end note]

    [ Example:

      // a.cpp
      struct S { std::meta::info m; };
      struct T;
      struct U { T *m; };
    
      // b.cpp
      struct S;
      struct T { S *m; };
    

    S, T, and U are all consteval-only types, even though neither T nor U is observably consteval-only from any point in the program. -- end example]

    Every object of consteval-only type shall be
    • the object associated with a constexpr variable or a subobject thereof,
    • a template parameter object (13.2 [temp.param]) or a subobject thereof, or
    • an object whose lifetime begins and ends during the evaluation of a core constant expression.
    Every function of consteval-only type shall be an immediate function (7.7 [expr.const]).
    Each declaration D of a variable or structured binding with consteval-only type T shall be either
    • constexpr or
    • introduced by the declaration of an object or reference whose lifetime begins and ends within a manifestly constant-evaluated expression;
    a diagnostic is required only if D is reachable from a program point from which T is observably consteval-only.

    Each declaration D of a function of consteval-only type T shall be either

    • consteval or
    • a declaration of an immediate-escalating function (7.7 [expr.const]);

    a diagnostic is required only if D is reachable from a program point from which T is observably consteval-only.

    [Note: Immediate-escalating functions of consteval-only type are immediate functions (7.7 [expr.const]). --end note]

    Each potentially-evaluated expression or conversion E of consteval-only type T shall be in an immediate function context; a diagnostic is required only if the innermost declaration that contains E is reachable from a program point where T is observably consteval-only.

    [Note: An expression is immediate-escalating if its type is observably consteval-only from the program point following the expression (7.7 [expr.const]). --end note]

  2. Change 7.7 [expr.const] paragraph 21 as follows:

    A constant expression is either
    • a glvalue core constant expression E for which
      • E refers to a non-immediate function,
      • E designates an object o, and if the complete object of o is of observably consteval-only type from the program point immediately following E then so is E,
      [Example 11: ... —end example] or
    • a prvalue core constant expression E whose result object (7.2.1 [basic.lval]) satisfies the following constraints:
      • each constituent reference refers to an object or a non-immediate function,
      • no constituent value of scalar type is an indeterminate or erroneous value (6.8.5 [basic.indet]),
      • no constituent value of pointer type is a pointer to an immediate function or an invalid pointer value (6.9.4 [basic.compound]),
      • no constituent value pointer-to-member type designates an immediate function, and
      • unless the value is of consteval-only type,
        • no constituent value of pointer-to-member type points to a direct member of a class that is observably consteval-only from the program point immediately following E class type,
        • no constituent value of pointer type points to or past an object whose complete object is of observably consteval-only type from the program point immediately following E, and
        • no constituent reference refers to an object whose complete object is of observably consteval-only type from the program point immediately following E.
  3. Change in 7.7 [expr.const] paragraph 24 as follows:

    A potentially-evaluated expression or conversion E is immediate-escalating if it is neither initially in an immediate function context nor a subexpression of an immediate invocation, and
    • it is an id-expression or splice-expression that designates an immediate function,
    • it is an immediate invocation that is not a constant expression, or
    • it is of observably consteval-only type from the program point immediately following E (6.9.1 [basic.types.general]).
  4. Change in 7.7 [expr.const] paragraph 26 as follows:

    An immediate function is a function that is
    • declared with the consteval specifier,
    • an immediate-escalating function whose type is observably consteval-only from the program point immediately following its definition (6.9.1 [basic.types.general]), or
    • an immediate-escalating function F whose function body contains either
      • an immediate-escalating expression or
      • a definition of a non-constexpr variable with whose type is observably consteval-only type from the program point immediately following the expression
      whose innermost enclosing non-block scope is F's function parameter scope.
    [Note 11: Default member initializers used to initialize a base or member subobject (11.9.3 [class.base.init]) are considered to be part of the function body (9.6.1 [dcl.fct.def.general]). —end note]
  5. Change in 11.7.3 [class.virtual] paragraph 18 as follows:

    A class with a consteval An immediate virtual function that overrides a virtual function that is not consteval immediate shall have consteval-only type be a member of a class C that is observably consteval-only from the program point immediate following the definition of C (6.9.1 [basic.types.general]). A consteval An immediate virtual function shall not be overridden by a virtual function that is not consteval an immediate function.
  6. Change the condition for is_consteval_only in 21.3.6.4 [meta.unary.prop] as follows:

    T is observably consteval-only (6.9.1 [basic.types.general]) from a program point in the instantiation context
Date: 2026-01-19.00:00:00

(From submission #836.)

A class type is consteval-only depending on its member types. However, a class type may be incomplete, and thus the question cannot be answered where needed.

For example,

  struct S;
  void f(S*);   // #1
  struct S {    // #2
    std::meta::info x;
  };

Does the class definition at #2 make the function declaration #1 retroactively ill-formed? What if #1 and #2 are not mutually reachable?

History
Date User Action Args
2026-03-01 21:55:49adminsetmessages: + msg8495
2026-01-23 23:04:37adminsetstatus: open -> drafting
2026-01-19 00:00:00admincreate