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!
}

そして、これがライブの例です。

備考:

std::function<>C++03 を使用している場合はboost::function<>、簡単に変更できます(実際、Boost.Function はインスピレーションを得て、後に標準 C++ ライブラリの一部になりました)。この場合、ヘッダーを含める代わりに、およびヘッダーを含める必要があります(後者は を使用する場合のみ)。std::bind<>boost::bind<>std::function<><functional>boost/function.hppboost/bind.hppboost::bind

std::function<>/boost::function<>があらゆる種類の呼び出し可能なオブジェクトをカプセル化する能力を通じてあなたに与える力を感じさせるさらなる例については、この Q&A on StackOverflowも参照してください。

于 2013-03-10T14:33:26.540 に答える
4

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;
}

これにより、上記と同様に、あらゆる種類の呼び出し可能なオブジェクトを渡すことができますが、おそらくラムダがインライン化されることはありません。

于 2013-03-10T14:36:07.680 に答える