Home > Enterprise >  Why does `consteval` not behave as expected?
Why does `consteval` not behave as expected?

Time:03-28

inline consteval unsigned char operator""_UC(const unsigned long long n)
{
    return static_cast<unsigned char>(n);
}

inline consteval char f1(auto const octet)
{
    return char(octet >> 4_UC);
}

inline constexpr char f2(auto const octet)
{
    return char(octet >> 4_UC);
}

int main()
{
    auto c1 = f1('A'); // ok
    auto c2 = f2('A'); // error

    return c1   c2;
}

Compiled with: clang -14 -std=c 20 -stdlib=libc , and the error message is:

undefined reference to `operator"" _UC(unsigned long long)'

See online demo

Why does f1() is ok while f2() is not?

Why does consteval not behave as expected?

CodePudding user response:

They do behave as expected. The diagnostic could be better, but the behavior is certainly what one should expect.

auto c2 = f2('A'); // error

Since c2 is not a constexpr variable, its initialisation doesn't have to be constant evaluated. And it in fact isn't. This means the full-expression of its initialisation is not a constant expression, and so f2 is a "runtime" function here.

Meanwhile char(octet >> 4_UC) is an immediate invocation of operator""_UC. There's a "shall requirement" attached to it.

[expr.const] (emphasis mine)

13 An expression or conversion is in an immediate function context if it is potentially evaluated and its innermost non-block scope is a function parameter scope of an immediate function. An expression or conversion is an immediate invocation if it is a potentially-evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context. An immediate invocation shall be a constant expression.

For c2, that requirement is violated. The code is ill-formed.

  • Related