Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Legitimate appearances of <=> in pre-c++20 code

Messing around in wandbox I discovered that clang will actually issue a warning if it sees <=> appear in C++17 or earlier.

warning: '<=>' is a single token in C++2a; add a space to avoid a change in behavior [-Wc++2a-compat]

I've tried to figure out how to write a legitimate use case of the character sequence <=> in C++17, but what I come up with all feel very contrived. The most likely example (imo) involves using a template:

struct A {
  bool operator<=(A) const { return true; }
};

template <auto Cmp>
void f() { }

int main() {
  f<&A::operator<=>();
}

live example

Everything else still involves explicitly mentioning the comparison function by name operator<=. Is there a more common appearance of <=> that I'm failing to imagine which would have motivated the clang developers to add this warning?

like image 389
Ryan Haining Avatar asked Mar 14 '18 00:03

Ryan Haining


1 Answers

There are some other possible syntaxes that don't necessarily involve a template argument like that. For example,

class A {};
bool operator<=(A,A) { return true; }

class B {};
bool operator>(bool(*)(A,A), B) { return false; }

int main()
{
    B b;
    return operator <=> b;
}

But it is true all such examples do have the keyword operator immediately before the appearance of <=>.

The only way to prove a claim like that is to do an exhaustive search through the entire C++ grammar, conveniently shown in one place in Appendix A of the C++17 Standard and some other Standard versions.

First, note that because of the Maximal Munch rule, if the next source characters after previous preprocessor tokens have been parsed are <=>, then C++17 and earlier will always treat the first token as <=. The next token could actually be > or >> or >= or >>=.

The only grammar rules involving the token <= are:

fold-operator:

    <=

relational-expression:

    relational-expression <= shift-expression

operator:

    <=

The grammar symbol fold-operator is only used in:

fold-expression:

    ( cast-expression fold-operator ... )

    ( ... fold-operator cast-expression )

    ( cast-expression fold-operator ... fold-operator cast-expression )

So as a fold-operator, <= must be followed by either the ... token (which is certainly not > or >> or >= or >>=), or a cast-expression. Either as a fold-operator or in a relational-expression, the <= token may be followed by a cast-expression or shift-expression, which are both restricted sorts of expression. But there is no grammar rule allowing any expression to begin with > or >> or >= or >>=.

That leaves just the grammar symbol operator, found only in:

operator-function-id:

    operator operator

which shows that the keyword operator must be immediately before the <= which might instead end up as part of a <=> in C++20.

like image 199
aschepler Avatar answered Oct 05 '22 23:10

aschepler