I recently came to know that for complex expression(like expressions involving operators) in a require-clause the standard requires the use of parentheses.
But then I wrote the following program where the use of ||
works without parentheses but the use of ==
is not allowed. Demo
template<typename T> struct C
{
constexpr static bool b = T{} + 1;
constexpr static bool c = T{} + 1;
};
//template<typename T> requires C<T>::b == C<T>::c void f(); //all compilers reject this
template<typename T> requires C<T>::b || C<T>::c void bar(); //all compilers accepts this
int main()
{
// f<int>(); //fails in all three compilers
bar<int>(); //works in all three compilers
}
I want to know why is the ==
version not compile but the ||
version does?
I want to know why is the == version not compile but the || version does?
Because the standard grammar explicitly allows ||
in a require-clause without parentheses but not ==
as explained below..
From requires-clause:
requires-clause: requires constraint-logical-or-expression constraint-logical-or-expression: constraint-logical-and-expression constraint-logical-or-expression || constraint-logical-and-expression ^^
As you can see, the use of ||
is allowed. Basically, the requires
has custom behavior for ||
and &&
.
But note ==
(and other operators) without parentheses is not allowed as also explained in the old post. For reference, there is also a non-normative note in the standard:
[ Note: The expression in a requires-clause uses a restricted grammar to avoid ambiguities. Parentheses can be used to specify arbitrary expressions in a requires-clause. [ Example:
template<int N> requires N == sizeof new unsigned short int f(); // error: parentheses required around == expression
ā end example] ā end note]