Передача аргументов указателя на функцию с boost

Можно ли упростить / улучшить следующую передачу указателя на функцию с помощью boost :: function и / или boost :: bind?

void PassPtr(int (*pt2Func)(float, std::string, std::string))
{
int result = (*pt2Func)(12, "a", "b"); // call using function pointer
cout << result << endl;
}

// execute example code
void Pass_A_Function_Pointer()
{
PassPtr(&DoIt);
}

1

Решение

Ты можешь использовать boost::function<> чтобы сделать возможным использование различных типов вызываемых объектов в качестве входных данных функции.

Ниже приведен пример использования C ++ 11 (см. Примечания после этого примера). Вот как бы вы переписали свою функцию:

#include <functional>
#include <string>
#include <iostream>

void PassFxn(std::function<int(float, std::string, std::string)> func)
//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
int result = func(12, "a", "b"); // call using function object
std::cout << result << std::endl;
}

Это пара функций для тестирования:

int DoIt(float f, std::string s1, std::string s2)
{
std::cout << f << ", " << s1 << ", " << s2 << std::endl;
return 0;
}

int DoItWithFourArgs(float f, std::string s1, std::string s2, bool b)
{
std::cout << f << ", " << s1 << ", " << s2 << ", " << b << std::endl;
return 0;
}

struct X
{
int MemberDoIt(float f, std::string s1, std::string s2)
{
std::cout << "Member: " << f << ", " << s1 << ", " << s2 << std::endl;
return 0;
}

static int StaticMemberDoIt(float f, std::string s1, std::string s2)
{
std::cout << "Static: " << f << ", " << s1 << ", " << s2 << std::endl;
return 0;
}
};

А вот и тестовая процедура:

int main()
{
PassFxn(DoIt); // Pass a function pointer...

// But we're not limited to function pointers with std::function<>...

auto lambda = [] (float, std::string, std::string) -> int
{
std::cout << "Hiho!" << std::endl;
return 42;
};

PassFxn(lambda); // Pass a lambda...

using namespace std::placeholders;
PassFxn(std::bind(DoItWithFourArgs, _1, _2, _3, true)); // Pass bound fxn

X x;
PassFxn(std::bind(&X::MemberDoIt, x, _1, _2, _3)); // Use a member function!

// Or, if you have a *static* member function...
PassFxn(&X::StaticMemberDoIt);

// ...and you can basically pass any callable object!
}

И вот живой пример.

ВЫСТУПЛЕНИЯ:

Вы можете легко изменить std::function<> в boost::function<> а также std::bind<> в boost::bind<> если вы работаете с C ++ 03 (на самом деле, Boost.Function является то, что вдохновило std::function<> а позже стал частью стандартной библиотеки C ++). В этом случае вместо включения <functional> заголовок, вам нужно будет включить boost/function.hpp а также boost/bind.hpp заголовки (последний, только если вы хотите использовать boost::bind).

Для дальнейшего примера, который должен дать вам ощущение силы, std::function<> / boost::function<> дает вам возможность инкапсулировать любой вызываемый объект, также смотрите этот вопрос&А на StackOverflow.

5

Другие решения

Я предполагаю, что вы хотите улучшить функциональность PassPtr, а не весь пример кода, который вы дали. Если вы используете C ++ 11 и можете использовать лямбда-выражения, я бы упростил это до:

template <typename Func>
void PassPtr(Func f) {
std::cout << f(12, "a", "b") << std::endl;
}

Это позволит любому вызываемому объекту быть переданным как f, Причина, по которой функция берется из выведенного типа шаблона, заключается в том, что любые передаваемые лямбда-выражения должны быть встроены. Конечно, это не приводит к наложению какой-либо конкретной подписи на переданную функцию (или на то, что это должен быть даже вызываемый объект). Например, если вы передаете intвы получите некоторые запутанные ошибки компилятора.

Альтернатива, использующая [boost|std]::function, это сделать это:

void PassPtr(std::function<int(float, std::string, std::string)> f) {
std::cout << f(12, "a", "b") << std::endl;
}

Это позволит передавать любой вызываемый объект, как указано выше, но, вероятно, не приведет к тому, что лямбда-выражения будут встроены.

3