Why do I need to include <compare> header to get <=> to compile?
Asked Answered
K

1

10

I know the technical answer is: because the standard says so.

But I am confused regarding the motivation:

I see nothing "library" in the defaulting the <=>: it may return some type that is technically defined in std but it is a "fake library" type in a sense that compiler must know about it since it must be able to default operator <=> with auto return type (not to mention that error messages in good compilers specify <compare> so it is clear that there is a language<=>library link here).

So I understand there is some library functionality that might require me to include <compare> but I do not understand why defaulting <=> requires me to include that header since compiler anyway has to know about everything needed to make the <=>.

Note: I know most of the time some other standard headers will include the <compare>, this is a question about language/library design, not that much about one extra line that C++ forces me to write without a good reason.

Kalliekallista answered 22/5, 2020 at 22:31 Comment(6)
Probably similar reason as why you need to include <new> in order to use placement new syntax.Seeker
And the same with <typeinfo> which is needed to simply use typeid.Maidservant
@Seeker it's interesting though that you don't need to include <new> in order to use the default non-placement operator new. So it seems that there's no technical reason to force users to include the header for these built-in operations.Oshinski
"it is a "fake library" type" There is no such thing. A type either is a fundamental type defined by the compiler or it isn't.Valiant
@Brian new is a language keyword, so there is no header for it. But placement-new can be overloaded by users, where <new> defines the default placement-newTicktack
It's a bit hard for anyone to answer this question unless they were involved in the standardisation process that developed and evolved the specifications related to the spaceship operator. Otherwise (and possibly even then) answers will almost certainly be opinion-based, since the standardisation process is political, proposals have imperfections that may take time to find, perfect designs may be difficult for compiler/library developers to implement but imperfect ones are more achievable.Jaynejaynell
H
7

it may return some type that is technically defined in std but it is a "fake library" type in a sense

Well, <=> returns types that are very much real, that are actually defined in <compare> and implemented there. In the same way that an initializer list is used to construct a std::initializer_list<T>, which is very much a real type that is actually defined in <initializer_list>. And typeinfo in <typeinfo>.

And those comparison types - std::strong_ordering, std::weak_ordering, and std::partial_ordering (and originally also std::strong_equality and std::weak_equality) - themselves have non-trivial conversion semantics and other operations defined on them, that we may want to change in the future. They'd be very special language types indeed, where the convertibility only goes in one direction but in a way that's very much unlike inheritance (there are only three values for the total ordering types, but four for the partial one...). It's really much easier to define these as real library types and then specify their interaction as real library code.

that compiler must know about it since it must be able to default operator<=> with auto return type

Kind of, but not really. The compiler knows what the names of the types are, and how to produce values of them for the fundamental types, but it doesn't actually need to know anything more than that. The rule for the return type is basically hardcoded based on the types that the underyling members' <=>s return, don't need to know what those actual types look like to do that. And then you're just invoking functions that do... whatever.

The cost of you having to include a header is typing #include <compare> and then parse it. The cost of the compiler having to synthesize these types is a cost that would have to be paid for every TU, whether or not it does any three-way comparisons. Plus if/when we want to change these types, it's easier to change library types than language types anyway.

Homogenesis answered 23/5, 2020 at 1:28 Comment(3)
"The compiler knows what the names of the types are, and how to produce values of them for the fundamental types, but it doesn't actually need to know anything more than that. " AFAIK compiler also needs to know to pick the weakest comparison category of composite members.Kalliekallista
@NoSense I covered that, no?Homogenesis
I to not think so since compiler needs to know a lot about those types, not just the name., but this is matter of an opinion... and not worth a lot of typing. I feel that basic comparison categories will never change and could have been hardoded in the language. But at least I know the motivation so I will accept the answer.Kalliekallista

© 2022 - 2024 — McMap. All rights reserved.