使用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);
}
答案 0 :(得分:6)
您可以使用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!
}
这是一个live example。
备注:
如果您正在使用C ++ 03,则可以轻松地将std::function<>
更改为boost::function<>
,将std::bind<>
更改为boost::bind<>
(实际上,Boost.Function是受到启发的{{}} {1}}后来成为标准C ++库的一部分。在这种情况下,您不必包含std::function<>
标头,而是必须包含<functional>
和boost/function.hpp
标头(仅当您要使用boost/bind.hpp
时才包含后者)。< / p>
对于另一个示例,应该让您感觉boost::bind
/ std::function<>
通过其封装任何类型的可调用对象的能力为您提供的力量,同时请参阅this Q&A on StackOverflow。< / p>
答案 1 :(得分:3)
我认为您希望改进PassPtr
的功能,而不是您提供的所有示例代码。如果您使用的是C ++ 11并且可以使用lambda表达式,我会将其简化为:
template <typename Func>
void PassPtr(Func f) {
std::cout << f(12, "a", "b") << std::endl;
}
这将允许任何可调用对象作为f
传递。通过推导出的模板类型获取函数的原因是允许传递的任何lambda都被内联。当然,这不会对传递的函数强制执行任何特定签名(或者它甚至应该是可调用对象)。例如,如果传递int
,则会出现一些混乱的编译器错误。
使用[boost|std]::function
的替代方法是:
void PassPtr(std::function<int(float, std::string, std::string)> f) {
std::cout << f(12, "a", "b") << std::endl;
}
这将允许传递任何类型的可调用对象,就像上面一样,但可能不会导致lambdas被内联。