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.