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.