Consider the following code snippet (compiled with clang19):
consteval bool IsEven(int n) {
return 0 == n % 2;
}
template<int n>
requires (IsEven(n)) // ok
void f1() {}
template<int n>
requires IsEven(n) // error: Atomic constraint must be of type 'bool'
// (found '<overloaded function type>')
void f2() {}
The cppref page tells me IsEven(n)
is not a primary expression. I just wonder:
Why is a consteval function expression NOT a primary expression?
This doesn't have anything to do with consteval. Primary expressions are simply a syntactic category of expression in the C++ grammar, and function calls aren't in that category.
A primary expression is required to avoid parsing ambiguity. The standard gives the following example:
template<int N> requires N == sizeof new unsigned short
int f();
If arbitrary expressions were allowed, it would be ambiguous whether the constraint is N == sizeof new unsigned short
and the return type is int
, or the constraint is N == sizeof new unsigned
and the return type is short int
.
It's possible the grammar could have allowed some or all function call expressions without formal ambiguity, but doing so would complicate the grammar without adding meaningful expressive power - the syntax is supposed to encourage the use of named concepts, and if you really want to write a function call, you can wrap it in parentheses, as you did.