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:
requires-clause: requires constraint-logical-or-expression
Now we move onto constraint-logical-or-expression:
constraint-logical-and-expression constraint-logical-or-expression || constraint-logical-and-expression
Next, we move onto constraint-logical-and-expression:
primary-expression constraint-logical-and-expression && primary-expression
So, now we go to primary-expression:
primary-expression: literal this ( expression ) id-expression lambda-expression fold-expression requires-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 before std::is_enum_v<T> without parentheses.
#include <type_traits>
template<typename T> requires !std::is_enum_v<T> //invalid per grammar rules
void foo(T)
{
}
template<typename T> requires std::is_enum_v<T> //valid per grammar rules
void bar(T)
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With