2

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

2 回答 2

7

您可以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!
}

这是一个活生生的例子

备注

如果您正在使用 C++03,您可以轻松地转换std::function<>boost::function<>std::bind<>转换成(事实上,Boost.Function 是受启发的,后来成为标准 C++ 库的一部分)。在这种情况下,您必须包含and标头,而不是包含标头(仅当您想使用时才包含标头)。boost::bind<>std::function<><functional>boost/function.hppboost/bind.hppboost::bind

另一个例子应该让你感受到std::function<>/boost::function<>通过它封装任何类型的可调用对象的能力给你带来的力量,另请参阅StackOverflow 上的这个问答

于 2013-03-10T14:33:26.540 回答
4

我假设您想改进 的功能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;
}

这将允许传递任何类型的可调用对象,就像上面一样,但可能不会导致 lambda 被内联。

于 2013-03-10T14:36:07.680 回答