Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: zero as null pointer constant while comparing template class using spaceship operator (<=>)

Tags:

c++

c++20

Similar question: warning: zero as null pointer constant while comparing iterators - that is about comparing iterators, this question is about comoparing template classes.

I was migrating c++14 codebase to c++20. however using spaceship operator gives an warning zero as null pointer constant, which i can't figure out why it's happening and what does the error mean.

used clang++14 with -std=c++20 -Werror -Wzero-as-null-pointer-constant.

below is the minimal reproducible example, also runnable on godbolt.

#include <compare>

template<typename V, typename U>
class quantity
{
    public:
        using value_type = V;
        using unit_type = U;
        using this_type = quantity<value_type, unit_type>;

        constexpr quantity() : value_() {}
        constexpr quantity( const value_type &v, unit_type ) : value_( v ) {}

        constexpr auto operator<=>( const this_type &rhs ) const = default;

    private:
        value_type value_;
};

class energy_in_joule_tag{};
using energy = quantity<int, energy_in_joule_tag>;

int main() {
    const energy lo = energy(0, energy::unit_type{} );
    const energy hi = energy(1000, energy::unit_type{} );

    energy out = energy(20, energy::unit_type{} );

    if( out < lo || out > hi ) {
        return 1;
    }
}
<source>:14:74: error: zero as null pointer constant [-Werror,-Wzero-as-null-pointer-constant]
        constexpr auto operator<=>( const this_type &rhs ) const = default;
                                                                         ^
                                                                         nullptr
<source>:29:13: note: in defaulted three-way comparison operator for 'quantity<int, energy_in_joule_tag>' first required here
    if( out < lo || out > hi ) {
            ^
1 error generated.
Compiler returned: 1

this is the entirity of the error message.

like image 448
scarf Avatar asked Apr 05 '26 15:04

scarf


1 Answers

Here's a more minimal example:

#include <compare>

struct quantity {
    int i;
    constexpr auto operator<=>( const quantity& ) const = default;
};

bool f(quantity a, quantity b) {
    return a < b;
}

What's actually happening here is that a < b evalutes as (a <=> b) < 0. The way that comparison categories are specified is that they can only be compared to specifically the literal 0. The only way you can really implement that in C++ is with some unspecified function pointer type - which means that 0 is really a null pointer constant, which this warning flags as saying you shouldn't use it.

But of course, you're not the one using 0, the language is. And it's not really a null pointer constant, it's kind of a hack to make the specification work and a hypothetical future language future might obviate the need for having to implement this with a pointer type.

The point is: your code is fine, this is a bad warning. Reported an issue.

like image 63
Barry Avatar answered Apr 08 '26 05:04

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!