使用boost传递函数指针参数

时间:2013-03-10 14:28:03

标签: c++ boost boost-bind boost-function

使用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);
}

2 个答案:

答案 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被内联。