clang-tidy vs 结构化绑定

Fra*_*ank 6 c++ c++17 clang-tidy

在 ubuntu 20.04 (10.0.0) 中打包的 clang-tidy 似乎在一个相当简单的代码块上窒息,它涉及结构化绑定和移动操作:

#include <memory>
#include <tuple>

struct T {
  ~T() {
    if(ptr != nullptr) { // clang-tidy is convinced ptr is uninitialized when the tuple is destroyed.

    }
  }

  T(T&& rhs) : ptr(rhs.ptr) {
    rhs.ptr = nullptr;
  }

  // Be very explicit for the sake of the MCVE.
  T() = default;
  T(const T&) = delete;
  T& operator=(T&&) = delete;
  T& operator=(const T&) = delete;

  int* ptr = nullptr;
};

std::tuple<T, T> foo();

void bar() {
  auto [a, b] = foo();

  T x = std::move(a);
  T y = std::move(b);
}

void baz() {
  auto a_b = foo();
  auto& a = std::get<0>(a_b);
  auto& b = std::get<1>(a_b);

  T x = std::move(a);
  T y = std::move(b);
}
Run Code Online (Sandbox Code Playgroud)

Clang-tidy 标记bar()为:

警告:'!=' 的左操作数是一个垃圾值 [clang-analyzer-core.UndefinedBinaryOperatorResult] if(ptr != nullptr) {

baz()就好了。

我宁愿不完全关闭该测试,并且在该比较线上添加 NOLINT 是...充其量是不确定的,尤其是因为它位于一个不相关的库中。(因为在库中不知道这些对象最终会在一个元组中)。

所以我的问题是:有没有办法在保持结构化绑定的同时解决这个问题?或者,clang-tidy 实际上就在这里,我非常误解结构化绑定是如何工作的?

FWIW,clang-tidy 正在通过 cmake 调用,如下所示:

set(CMAKE_CXX_CLANG_TIDY clang-tidy;--format-style=file)
Run Code Online (Sandbox Code Playgroud)