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

Time:06-08

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.

CodePudding user response:

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.

  • Related