C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Let spaceship return an int

From: Thiago Macieira <thiago_at_[hidden]>
Date: Tue, 26 Sep 2023 22:27:26 -0700
On Tuesday, 26 September 2023 20:34:16 PDT Chris Gary via Std-Proposals wrote:
> I fail to see why a strongly-typed ternary, mandatory for use with <=>,
> provides an adequate solution to this problem. Especially where the
> operator is user-defined.
> All it does is create what I consider to be a nuisance of a dependency.

Because that's not the problem it solves.

No one is arguing that four values can't be represented in int. No one is
arguing that optimal code can't be generated.

The use of a strong type solves two problems that int doesn't: semantic and
combination. Semantic allows code to know the difference between equality in
strongly-comparable types and equivalence in weakly-ordered ones. You may not
care about that difference, but other people do. The strong typing also allows
one to know whether the result can be unordered or not: if it can't be
unordered, you don't need to implement the lookup tables you described at all.

Combination is particularly important for generic code: how do you write
operator<=> for std::vector<T> or std::tuple<T...> ? For tuples, it's a
heterogeneous list, so the types may be weakly ordered, strongly ordered or
only partially ordered. So what is the result of the three-way compare?

Moreover, semantic gives meaning where int doesn't. Let's take these two very,
very similar functions that return int from the C / POSIX library:

int memcmp(const void *, const void *, size_t);
int bcmp(const void *, const void *, size_t);

As we all know, memcmp() performs a three-way comparison and returns negative,
zero, and positive for less than, equal, and greater than byte comparisons.
bcmp() does not. It returns zero for equal and non-zero otherwise. But does
the return type convey that meaning? No. Will people mistake one for the
other? They most surely will.

And have. In fact, since in most C libraries bcmp() is implemented as an alias
to memcmp(), it has returned negative and positive as people might have
expected. This is so bad that when glibc attempted to implement a slightly
faster bcmp() that didn't return negative/positive, it broke all sorts of user
code. So glibc added __memcmpeq() instead.

Plain integers are bad to convey semantic meaning. I'm just going to give
another example that we found lurking in our codebase for 3 years:

    if (posix_fallocate(fd, 0, size)) {
        int saved_errno = errno;
        log_warning("could not create temporary file: %s", strerror(errno));
        close(fd);
        return -saved_errno;
    }

See if you can spot the error.

PS: it's slightly ironic that memcmp() would not be a good example of your
suggestion, in spite its returning an int.
-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DCAI Cloud Engineering

Received on 2023-09-27 05:27:28