Могу ли я привязываться к функции, которая принимает аргументы по умолчанию, а затем вызывает ее? - программирование
Подтвердить что ты не робот

Могу ли я привязываться к функции, которая принимает аргументы по умолчанию, а затем вызывает ее?

Как я могу привязать к функции, которая принимает аргументы по умолчанию, без указания аргументов по умолчанию, а затем вызывать ее без каких-либо аргументов?

void foo(int a, int b = 23) {
  std::cout << a << " " << b << std::endl;
}

int main() {
  auto f = std::bind(foo, 23, 34); // works
  f();


  auto g = std::bind(foo, 23); // doesn't work
  g();

  using std::placeholders::_1;
  auto h = std::bind(foo, 23, _1); // doesn't work either 
  h();

}
4b9b3361

Ответ 1

В принципе, каждый раз, когда вы пишете foo(x), компилятор переводит его на foo(x, 23);. Он работает только в том случае, если у вас есть прямой вызов с именем функции. Вы не можете, например, назначить &foo на void(*)(int), потому что подпись функции void(int, int). Параметры по умолчанию не играют роли в подписи. И если вы присваиваете его переменной void(*)(int, int), информация о параметре по умолчанию теряется: вы не можете использовать параметр по умолчанию через эту переменную. std::bind хранит void(*)(int, int) где-то в его недрах и, таким образом, теряет информацию о параметрах по умолчанию.

В С++ нет способа получить значение по умолчанию параметра из-за пределов функции, поэтому вы привязываетесь вручную, предоставляя значение по умолчанию при связывании.

Ответ 2

Я думаю, вы могли бы имитировать поведение, которое вы хотите, используя лямбда.

Что-то вроде этого:

auto g = [] (){ foo( 23 ); };

EDIT: просто проверено и, кажется, работает нормально: http://ideone.com/SPSvi

Ответ 3

У меня есть два решения:

1 - Вы можете перегрузить foo() и вызвать вызов оригинала по умолчанию:

void foo(int a, int b) 
{
    std::cout << a << " " << b << std::endl;
}

inline void foo(int a)
{
    foo(a, 23);
}

2 - Вы можете использовать статическую переменную по умолчанию, а затем использовать ее в процессе привязки:

static int foo_default_b = 23;
void foo(int a, int b = foo_default_b) 
{
    std::cout << a << " " << b << std::endl;
}

auto g = std::bind(foo, 23, foo_default_b);
g();

Ответ 4

Этот ответ не согласен с ответом Р. Мартиньо Фернандеса. Вы действительно можете использовать boost::bind для привязки к параметрам по умолчанию, вам просто нужно поместить заполнители, так:

boost::bind<void (int, int)>(foo, _1, _2)(12);

Это вызовет foo(12, 23), как и ожидалось. Хотя я не тестировал этот конкретный код, я сделал что-то подобное в своем коде на основе ответа, связанного выше, и работает в gcc 4.8.5.

Хм, я только заметил, что это спрашивает о std::bind, а не boost::bind. Я не знаю, какие отличия есть, если они есть.