I've written the following program that uses requires without parentheses. The program compiles with msvc but not with gcc and clang. I want to know which compiler is right here. Demo
#include <type_traits>
template<typename T> requires !std::is_enum_v<T>
void foo(T)
{
}
int main()
{
foo(4); //msvc compile but not gcc and clang
}
GCC says:
<source>:3:31: error: expression must be enclosed in parentheses
3 | template<typename T> requires !std::is_enum_v<T>
| ^~~~~~~~~~~~~~~~~~
| ( )
Compiler returned: 1
Note that I am not looking for a workaround as I know that I can solve this by writing parentheses around !std::is_enum_v<T>. I want to know which compiler is right here for academic purposes.
The program is ill-formed as per the current grammar rules as shown below.
From requires-clause documentation:
Now we move onto constraint-logical-or-expression:
Next, we move onto constraint-logical-and-expression:
So, now we go to primary-expression:
Now, the expression
!std::is_enum_v<T>fits neither of the above listed constructs. One might think that it is an id-expression but that is not the case.This means that we can't use
!etc beforestd::is_enum_v<T>without parentheses.