Вы можете использовать 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.
person
Andy Prowl
schedule
10.03.2013
cout << DoIt(12, "a", "b") << endl;
, но я думаю, это не то, что вам нужно. Тем не менее, здесь нет очевидных возможностей воспользоваться функциями Boost, поскольку вы вызываете чистый указатель на функцию, а не объект функции и т. д. - person Oliver Charlesworth   schedule 10.03.2013boost::bind
(илиstd::bind
) вы можете привязать любой количество аргументов перед передачей объекта функции. - person Some programmer dude   schedule 10.03.2013PassPtr
иDoIt
фиксированы, то нет, код настолько прост, насколько это возможно. - person CB Bailey   schedule 10.03.2013