modernize-avoid-bind

该检查会查找 std::bindboost::bind 的使用,并将它们替换为 lambda 表达式。除非使用 std::refboost::ref 显式请求引用捕获,否则 lambda 表达式将使用值捕获。

它支持任意可调用对象,包括成员函数、函数对象和自由函数,以及所有变体。您可以传递给 bind 的第一个参数的任何内容都应该可以被诊断。目前,唯一已知的修复无法支持的情况是当在参数列表中多次指定相同的占位符时。

给定

int add(int x, int y) { return x + y; }

然后

void f() {
  int x = 2;
  auto clj = std::bind(add, x, _1);
}

被替换为

void f() {
  int x = 2;
  auto clj = [=](auto && arg1) { return add(x, arg1); };
}

std::bind 可能难以阅读,并且由于等效 lambda 表达式不会生成的类型信息,可能会导致更大的对象文件和二进制文件。

选项

PermissiveParameterList

如果将该选项设置为 true,则检查将在每个占位符参数列表的末尾追加 auto&&...。如果没有此选项,在 bind 的结果在类型擦除函数对象(如 std::function)的上下文中使用的情况下,修复可能会执行不正确的转换,该函数对象允许不匹配的参数。例如

int add(int x, int y) { return x + y; }
int foo() {
  std::function<int(int,int)> ignore_args = std::bind(add, 2, 2);
  return ignore_args(3, 3);
}

是有效的代码,并返回 4。传递给 ignore_args 的实际值将被忽略。如果没有 PermissiveParameterList,它将被转换为

int add(int x, int y) { return x + y; }
int foo() {
  std::function<int(int,int)> ignore_args = [] { return add(2, 2); }
  return ignore_args(3, 3);
}

它将不会编译,因为 lambda 不包含接受 2 个参数的 operator()。使用允许的参数列表,它会生成

int add(int x, int y) { return x + y; }
int foo() {
  std::function<int(int,int)> ignore_args = [](auto&&...) { return add(2, 2); }
  return ignore_args(3, 3);
}

这是正确的。

此检查需要使用 C++14 或更高版本才能运行。