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

1

17

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?

Koger answered 14/3, 2018 at 0:43 Comment(9)
Even if there is no legitimate use case, it is still a breaking change that is reasonable for clang to call out. After all, that's the whole point of the warning: To signal any potential C++2a issues.Vestpocket
@RaymondChen I'm not trying to say it's not a reasonable warning regardless, I'm just surprised to see it this early on, and wondered if I was missing something obvious.Koger
If there were a non-contrived breakage scenario, I doubt that the committee would have voted in the change.Bisk
@RyanHaining: "what I come up with all feel very contrived" The fact that they're all contrived is precisely why 1) C++20 is using <=> for this operator rather than something else, since the change won't break much code, and 2) Clang is giving a warning, since they know it won't be triggered very often.Wisteria
Is a warning in C++17 mode necessary? The above code would not be valid in C++20 because the the template argument list is not closed. So compiling with -std=c++20 will emit a compile-time error.Italy
Probably the question should be rephrased: Is there a legitimate use case for <=>in C++17, which is also syntactically valid code in C++20 but with different semantics.Italy
@Italy sort of if a c++20 developer adds a definition for operator<=> in that exampleKoger
Yeah, since the operator-function-id syntax never names a builtin operator, you would need some declaration of an operator<=> for a program like this to be valid in both C++17 and C++20. Of course, you can't declare one yourself and have it be valid C++17. And it looks like none of the standard headers declare any operator<=> ... yet. But probably there should be some.Mirza
... and we're back to having to put spaces in template argument lists again :o)Birdcage
M
17

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.

Mirza answered 14/3, 2018 at 1:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.