Как сохранить объект boost::bind как переменную-член?

Я использую boost::bind для создания составных функций «на лету» и надеюсь сохранить объект как некоторую переменную-член класса для последующего использования. Например, у нас есть два функтора:

struct add{double operator()(double x, double y) const{return x+y;};};  
struct multiply{double operator()(double x, double y) const{return x*y;};};  

Затем, чтобы создать функцию f(x,y,z) = (x+y)*z, я могу сделать следующее:

auto f = boost::bind<double>(multiply(), boost::bind<double>(add(), _1, _2), _3);

И вызов f(x,y,z) работает отлично. Теперь я хочу сохранить f как переменную-член класса, что-то вроде следующего:

struct F  
{  
  auto func;  
  double operator(const std::vector<double>& args) const  
  {  
    return func(args[0],args[1],args[2]); //Skipping boundary check  
  }  
}

F f_obj;  
f_obj.func = f;  
f_obj(args);  

Но, конечно, я не могу объявить переменную auto. Есть ли способ обойти это?

Обратите внимание, что я не использую boost::function, так как это сильно повлияет на производительность, что для меня важно.

Спасибо за любой совет.


person matII    schedule 05.05.2014    source источник


Ответы (2)


Два варианта: использовать boost::function и измерить, действительно ли это влияет на производительность.

В качестве альтернативы сделайте F шаблоном, принимающим тип func в качестве параметра, и выведите его из типа выражения bind.

РЕДАКТИРОВАТЬ: Проблема со вторым вариантом заключается в том, что он не избавляет от неудобного типа. Вы можете сделать это, определив базовый класс с чистой виртуальной функцией, которую шаблон переопределяет. Но тогда у вас есть динамическая память для управления и стоимость виртуальной функции для оплаты - так что вы можете также вернуться к boost::function (или std::function), который делает для вас то же самое.

person Alan Stokes    schedule 05.05.2014
comment
boost::function — это первое, что я попробовал, но компилятор не может встроить оболочку boost::function. Из моего теста использование boost::function примерно в 5 раз медленнее, чем собственный код, в то время как использование boost::bind напрямую не имеет заметных накладных расходов. - person matII; 06.05.2014

Тип, возвращаемый из bind(), зависит от каждой комбинации функциональных объектов и аргументов. Если вы хотите сохранить результат, вам нужно каким-то образом стереть тип. Очевидный подход — использовать function<..>.

Когда результирующий функциональный объект вызывается часто, накладные расходы, вызванные function<...>, эффективно выполняющим виртуальную диспетчеризацию, могут быть слишком высокими. Один из подходов к решению этой проблемы состоит в том, чтобы связать объект функции с подходящими массовыми операциями и вместо сохранения объекта функции хранить подходящее приложение. Это не поможет, когда нужны отдельные звонки, но когда требуется много звонков, виртуальная диспетчеризация оплачивается только один раз.

person Dietmar Kühl    schedule 05.05.2014
comment
Очень интересная идея. Не могли бы вы привести пример, как это реализовано? - person matII; 06.05.2014