【问题标题】:What does comparing the result of the three-way comparison operator with nullptr do?将三路比较运算符的结果与 nullptr 进行比较有什么作用?
【发布时间】:2020-12-05 05:39:34
【问题描述】:

鉴于cppreference on <=>中的示例,我们可以将示例代码简化为:

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;
        }
    }
};

但我的 IDE (CLion 2020.2) 通过 clang-tidy 警告 result != 0 实际上应该是 result != nullptr。我不知道我们可以将std::###_orderingnullptr 进行比较。还请参考claims that we should rather compare it with literal 0。那里没有关于nullptr 的内容。

这段代码:

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

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

编译(GCC 10.1.0,Rev3,由 MSYS2 项目构建)并产生与0nullptr 版本相同的结果。


但是,我的 IDE 也警告我应该使用 p1 &lt; p2 来“Clang-Tidy: Use nullptr”。通过应用“修复”,代码更改为std::cout &lt;&lt; (p1 nullptr p2);,但它不会编译。它暗示它可能是 clang-tidy 中的一个错误,但它没有解释为什么我们可以将排序与nullptr 进行比较。为什么我们可以,为什么它有效,我们为什么想要它?

【问题讨论】:

  • 在您发布的代码中没有提到nullptr..
  • 您的 IDE 不是 C++ 编译器。只有真正的编译器才能完全理解 C++ 代码。尤其是较新版本的 C++。 IDE 错误解析 C++ 代码并不奇怪。
  • @JesperJuhl "并产生与0nullptr 版本相同的结果。" - 我的意思是如果我们实际上将if (const auto result = name &lt;=&gt; p.name; result != 0) 替换为@987654341 @,代码编译并产生预期的结果。
  • @SamVarshavchik:“clang-tidy 也不是 C++ 编译器。它从 C++ 编译器中借用了一些代码,但它本身并不是一个完整的 C++ 编译器。“我不知道这与这个问题有什么关系。 Clang-tidy 并不是说​​代码不会编译或无效甚至损坏;它提供了关于它认为是编写该代码的更好方法的建议。这就是它的工作;在这种情况下肯定是错误的,但这就是它想要做的。
  • 至于“老”operator &lt;auto operator &lt;=&gt; (const person&amp; p) const { return std::tie(name, surname) &lt;=&gt; std::tie(p.name, p.surname); ) :)(甚至这里是= default; ;))

标签: c++ c++20 nullptr spaceship-operator


【解决方案1】:

但我的 IDE (CLion 2020.2) 通过 clang-tidy 警告 result != 0 实际上应该是 result != nullptr

这是错误的。应该是result != 0。比较类别被指定为仅可与 literal 0 进行比较。

检查可能来自这样一个事实,即在 C++20 中实现与文字 0 进行比较的唯一真正方法是采用类型为指向成员指针的未指定指针或函数指针的参数 - 和 clang -tidy 可能会将您作为参数提供给指针的任何0 标记为应该nullptr。大多数时候,这是正确的。只是这里不具体。事实上,如果你写 result != nullptr 它可能会编译 - 但这是错误的,你不应该这样做。

这是一个clang-tidy问题,它需要了解对于比较类别,它不应该以这种方式标记文字0的使用。

【讨论】:

  • 所以这似乎是一个愚弄clang-tidy的实现细节。谢谢,这很有道理。
  • 同样,virtual void foo() = nullptr; 也是 no bueno
  • @Eljay 当然,但这不是一回事——这是需要0 的语法,而这或多或少是一种实现技巧。
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 2018-05-29
  • 1970-01-01
  • 2012-05-29
  • 1970-01-01
  • 2015-09-22
  • 2012-05-12
  • 2011-04-04
相关资源
最近更新 更多