Почему std:: bind может быть назначен аргумент-несогласованный std:: function?

У меня есть код следующим образом:

#include <functional>
#include <iostream>
using namespace std;
void F(int x) {
  cout << x << endl;
}
int main() {
  std::function<void(int)> f1 = std::bind(F, std::placeholders::_1);
  f1(100);  // This works, will print 100.

  int x = 0;
  std::function<void()> f2 = std::bind(F, x);
  f2();  // This works, will print 0.

  std::function<void(int)> f3 = std::bind(F, x);
  f3(200);  // BUT WHY THIS WORKS?????? It prints 0.
  return 0;
}

Моя информация о компиляторе: Apple LLVM версии 6.0 (clang-600.0.56) (на основе LLVM 3.5svn) Цель: x86_64-apple-darwin13.4.0 Модель темы: posix

Ответ 1

Это правильное поведение.

std::bind нуждается в этой непринужденности, чтобы соответствовать ее собственной спецификации.

Рассмотрим std::placeholders, который используется для отметки параметров, которые передаются связанной функции.

using std::placeholders;
std::function<void(int)> f2 = std::bind( F, _1 );
//  Parameter 1 is passed to                ^^
//  the bound function.

f2(7); // The int 7 is passed on to F

Аналогично, для второго параметра _2, _3 для третьего и т.д.

Это вызывает интересный вопрос. Как должен вести себя этот объект функции?

auto f3 = std::bind( F, _3 );

Как вы можете себе представить, он следует своему собственному обещанию передать третий параметр в F. Это означает, что он ничего не делает для первых двух параметров.

f3(10, 20, 30); // The int 30 is passed on to F. The rest?  Ignored.

Итак, это ожидаемое поведение и, возможно, единственная "функция", которая std::bind выполняется над lambdas, даже в С++ 14.

Объект, созданный std::bind, предназначен для принятия и игнорирования любых посторонних параметров.