Как вызвать объект boost :: function со всеми связанными аргументами - PullRequest
0 голосов
/ 14 февраля 2019

Я читал на boost::function и boost::bind, однако я не могу найти "хороший способ" вызвать функцию boost, если все аргументысвязаны (я думаю, что это правильная терминология).Ниже приведен непроверенный MCVE (копирование и вставка моего реального кода не идеальны).

#include "boost/function.hpp"
#include "boost/bind.hpp"
#include <iostream>

void func(void* args)
{
  int* myInt = static_cast<int*>(args);
  if (myInt != NULL)
  {
    std::cout << "myInt = " << *myInt << std::endl;
  }
  else
  {
    std::cout << "args is NULL" << std::endl;
  }
}

int main()
{
  int myInt1 = 5;
  int myInt2 = 45;

  boost::function<void(void* args)> myFunc = boost::bind(&func, &myInt1);

  // here's my problem,, how do I call myFunc?
  myFunc();  // this does not compile due to missing arguments
  myFunc;    // this is essentially a no-op. The function doesn't execute,
             // and if I put a breakpoint here, it either goes to the next
             // line or I get a warning that no executable code exists here

  // after some experimentation, I realized I can do this and it works
  myFunc(NULL);  // this prints out "myInt = 5"

  // this also prints out "myInt = 5"
  boost::bind(&func, &myInt1)();

  // finally, this prints out "myInt = 5" as well
  myFunc(&myInt2);

  return 0;
}

Итак, мой вопрос, какой предпочтительный / правильный способ вызова myFunc?Я успешно вызывал функции с заполнителями аргументов _1, _2 и т. Д., Передавая соответствующие аргументы. Может быть, на практике заполнители используются почти всегда?myFunc(NULL) работает, но мне кажется глупым, что я должен по существу выдвигать аргументы, если я их уже связал (и то, что я передаю, в любом случае не имеет значения).В моем реальном коде я на самом деле хочу вызвать myFunc в другой функции (поэтому boost::bind(&func, &myInt1)(); не вариант), и я делаю это внутри объекта класса, поэтому я надеюсь, что примерпри условии, демонстрирует поведение, идентичное тому, что я вижу в моем реальном коде.Я использую Visual Studio 2013, и c ++ 11 или более поздняя версия не может быть использована.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Лучшим типом для вашей переменной myFunc будет boost::function<void()>, поскольку со всеми аргументами исходной привязки func на самом деле не требуется никаких аргументов для вызова полученной оболочки.

boost::function<void()> myFunc = boost::bind(&func, &myInt1);

Это фактически позволит вам вызывать функцию с помощью:

myFunc();

Но причина, по которой компилятор допустил тип boost::function<void(void*)>, заключается в том, что результат вызова boost::bind может быть вызванс большим количеством аргументов, чем необходимо, если вы решите, и дополнительные аргументы просто игнорируются.Это делает некоторые ситуации более последовательными:

void f(int, int);
// g1 acts the same as f:
boost::function<void(int, int)> g1 = boost::bind(f, _1, _2);
// g2 swaps the order of arguments when calling f:
boost::function<void(int, int)> g2 = boost::bind(f, _2, _1);
// g3 ignores its first argument and passes the second to f twice:
boost::function<void(int, int)> g3 = boost::bind(f, _2, _2);
// g4 ignores its second argument and passes the first to f twice:
boost::function<void(int, int)> g4 = boost::bind(f, _1, _1);

При инициализации g4 мы можем сказать, что выражение bind - это просто еще одна связанная функция, которую можно вызывать ровно с двумяint аргументов, потому что он не использует никаких заполнителей с позицией больше 2. Его также можно вызывать только с одним аргументом, так как сам _2 также никогда не используется, но это не делает вышеприведенное ложным.

Аналогично, в вашем коде, инициализирующем boost::function<void(void*)>, компилятор принимает полностью связанное выражение bind как что-то, что может быть достоверно вызвано с одним аргументом, так как он не использует заполнители с положением, большим чем1. Хотя на самом деле он не использует заполнитель _1 с позицией ровно 1, ввод void* при таком использовании просто игнорируется.

0 голосов
/ 14 февраля 2019

Функциональный объект с «привязкой всех параметров» не имеет параметров, поэтому его тип будет boost::function<void()>.Вам нужно

boost::function<void()> myFunc = boost::bind(&func, &myInt1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...