modernize-avoid-bind

The check finds uses of std::bind and boost::bind and replaces them with lambdas. Lambdas will use value-capture unless reference capture is explicitly requested with std::ref or boost::ref.

It supports arbitrary callables including member functions, function objects, and free functions, and all variations thereof. Anything that you can pass to the first argument of bind should be diagnosable. Currently, the only known case where a fix-it is unsupported is when the same placeholder is specified multiple times in the parameter list.

Given:

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

Then:

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

is replaced by:

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

std::bind can be hard to read and can result in larger object files and binaries due to type information that will not be produced by equivalent lambdas.

Options

PermissiveParameterList

If the option is set to true, the check will append auto&&... to the end of every placeholder parameter list. Without this, it is possible for a fix-it to perform an incorrect transformation in the case where the result of the bind is used in the context of a type erased functor such as std::function which allows mismatched arguments. For example:

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

is valid code, and returns 4. The actual values passed to ignore_args are simply ignored. Without PermissiveParameterList, this would be transformed into

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

which will not compile, since the lambda does not contain an operator() that accepts 2 arguments. With permissive parameter list, it instead generates

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

which is correct.

This check requires using C++14 or higher to run.