Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does comparing the result of the three-way comparison operator with nullptr do?

Given the example from cppreference on <=>, we can simplify the example code to:

struct person {
    std::string name;
    std::string surname;

    auto operator <=> (const person& p) const {
        if (const auto result = name <=> p.name; result != 0) {
            return result;
        } else {
            return surname <=> p.surname;
        }
    }
};

But my IDE (CLion 2020.2), via clang-tidy, warns that result != 0 should actually be result != nullptr. I didn't know that we can compare std::###_ordering with nullptr. Cpprefence also claims that we should rather compare it with literal 0. There is nothing about nullptr there.

This code:

int main() {
    person p1{"ccc", "vvv"};
    person p2{"aaa", "zzz"};

    std::cout << (p1 < p2);
}

compiles (GCC 10.1.0, Rev3, Built by MSYS2 project) and yields identical results to both the 0 and the nullptr version.


However, my IDE also warns me that I should "Clang-Tidy: Use nullptr" with p1 < p2. By applying the "fix", the code changes to std::cout << (p1 nullptr p2); which, well, doesn't compile. It hints that it may be a bug in clang-tidy, but it doesn't explain why we can compare the orderings with nullptr. Why we can, why does it work and why would we want that?

like image 992
Fureeish Avatar asked Aug 15 '20 15:08

Fureeish


People also ask

Can you compare Nullptr?

Can you compare nullptr to other pointers for order? No, you cannot have ordered comparisons of nullptr or other null pointer constants with pointers.

Which is the comparison operator?

Comparison operators can compare numbers or strings and perform evaluations. Expressions that use comparison operators do not return a number value as do arithmetic expressions. Comparison expressions return either 1 , which represents true, or 0 , which represents false.


Video Answer


1 Answers

But my IDE (CLion 2020.2), via clang-tidy, warns that result != 0 should actually be result != nullptr.

This is wrong. It should be result != 0. The comparison categories are specified to only be comparable against the literal 0.

The check likely comes from the fact that the only real way to implement comparing against the literal 0 in C++20 is to take an argument whose type is some unspecified pointer or function pointer to pointer to member - and clang-tidy likely flags any 0 that you provide as an argument to a pointer as something that should be nullptr. Most of the time, this is correct. Just not specifically here. And indeed, if you write result != nullptr it probably will compile - but that's wrong and you should not do it.

This is a clang-tidy problem, it needs to understand that for comparison categories, it should not flag the use of literal 0 in this way.

like image 182
Barry Avatar answered Dec 06 '22 17:12

Barry