c++c++20terminologyconsteval

A name for describing `consteval` function argument being known at compile time but not constexpr


Argument of consteval function is:

The motivation behind this behavior is explained by Andrew Sutton in his paper Translation and evaluation: A mental model for compile-time metaprogramming, as pointed by this SO post.


You can return the argument from a consteval function and use it as a constexpr:

consteval int foo(int n) {
    return n;
}

constexpr int i = foo(9);

But you cannot use it as constexpr inside the consteval function itself:

// fails to compile
consteval int abs(int n) {
    if constexpr (n < 0) {
        return -n;
    }
    else {
        return n;
    }
}

Above fails to compile, as n is not a constexpr.

You can of course use a simple if, which would be evaluated at compile time:

// compiles
consteval int abs(int n) {
    if (n < 0) {
        return -n;
    }
    else {
        return n;
    }
}

constexpr int i = -9;
constexpr int num = abs(i);

This is a terminology question:

Is there a commonly used name for being known at compile time, but not being a constant expression?


Solution

  • TL;DR: No, there is no term for such a thing in the C++ standard.

    As far as the standard is concerned, "known at compile time" is not a thing. There is the concept of a "constant expression" and there is the concept of "constant evaluation".

    A constexpr function (a function declared with constexpr or consteval) can be called in a constant expression context. A constant expression context is a place where the language requires an expression to be a constant expression. Template arguments, initializers for constexpr/constinit variables, and so forth are constant expression contexts.

    When constexpr functions are called in a constant expression context, they produce constant expressions... or you didn't construct your function/arguments correctly and get a compile error. That's pretty much it, as far as the standard is concerned.

    Oh yes, there are rules about constexpr functions. They are forbidden from performing certain C++ actions. And there are rules about invoking them from a constant expression context. But otherwise, that's it.

    The distinction you're referring to is merely an outgrowth of what is allowed within a constexpr function. You can return the parameter of a constexpr function because the return value of a constexpr function is not grammatically a constant expression. That function can undergo constant evaluation given the right circumstances, but that's about all the standard needs to say on the subject.

    The parameter itself is not special to C++. What's special is what the function's definition is (ie: is your function valid in accord with constexpr rules, and does this evaluation do non-constexpr things), how the function was called (ie: did you call it in a constant expression context), and how the parameter got filled in (ie: was the argument a constant expression).

    To the standard, there are expressions which are constant expressions and expressions which are not. But expressions whose values are generated via constant expression evaluation but are not themselves linguistically constant expressions is just not a concept the standard needs to define. They're just values; whether they're in constant expression evaluation or not is not really relevant to the behavior of the program.

    So there is no name for such things.

    An immediate function (a function declared with consteval) is just a constexpr function with a couple of extra rules in it. Those rules prevent you from leaking the address of an immediate function (ie: compilers don't have to generate real functions for them). And the standard says that invoking an immediate function is always a constant expression context (and therefore must be invoked in accord with those rules).