c++language-lawyerrequires-clause

Expression without parentheses works in one case but not in other


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?


Solution

  • 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]