2013-09-03 48 views
5

簡単に言えば、関数オブジェクト/ lambdaとメンバ関数を簡素化して簡潔に定義する方法はありますか?メンバ関数を持つC++ 11でstd :: function/mem_fnを使用する

私はSTDを使用している場合、私は、右理解していれば:: mem_fnの、私は関数呼び出しに正しい型のオブジェクトを渡す必要があり、すなわち

Object o; 
ftncall std::mem_fun(&Object::function); 
ftncall(o); 

理想的には、「添付するいくつかの方法があるでしょう'oをその関数オブジェクトに(おそらくstd::weak_ptr)、削除されたかどうかわかります。漠然とこのような何かを行う方法があった場合たとえば、:

Object o; 
ftncall std::mem_fn(&Object::function, o); // Or maybe std::mem_fn<Object> 
ftncall(); 

は、明らかに、これは(私の知る限りでは)存在しません。 Std :: mem_fnの一般性(そして素敵さ)を失わないように、std :: mem_fnをラップする方法はありますか?oを「アタッチ」することはできますが、他の関数タイプと同様にうまくいきます。 std :: function?理想的には、std :: functionのやり方ではまだoperator()を使用することができます。

template<class T> 
class MemFunWrapper { 
public: 
    MemFunWrapper(T* t, std::mem_fun funct) : m_t(t), m_function(funct) {} 

    std::mem_fun operator*() { return m_function; } 
    T* get() { return m_t; } 
private: 
    T* m_t; 
    std::mem_fun m_function; 
} 

次に、あなたは以下のようなものを、それを使用することができます:

(*MemFunWrapper)(MemFunWrapper->get(), args...); 

しかし、それは私にはかなり扱いにくいと思われるが

現在、私は考えることができる最善の解決策は、次のようになりますクラスです。また、std :: functionと同等のクラスを作成する必要があります。これは、同様の方法で使用することができます。理想的には、メンバー関数または正規関数を呼び出すかどうかを知らずに最終製品を使用することもできます。私は多くを求めていることを知っています - どの方向性が役立つでしょう。どうもありがとう!

答えて

10

あなたが探していることはstd ::である代わりにのstd :: mem_fnののバインド:

#include <iostream> 
#include <functional> 

struct Object 
{ 
    void member() 
    { 
    std::cout << "yay!" << std::endl; 
    } 
}; 

int main() 
{ 
    Object o; 
    auto fn = std::bind(&Object::member, o); 
    fn(); 
} 

FWIW:はstdする過負荷を加える:: mem_fnのはCに含めるためのオブジェクトを受け入れるためのproposalあります++ 14。 C++ 11では

+1

どうもありがとうございます - あなたは私の希望と夢をすべて満たしているかもしれません! –

+0

'auto fn = std :: bind(&Object :: member、o);' auto fn = std :: bind(&Object :: member、&o); '、' std: :bind' –

+0

あなたの意図にもよりますが、両方とも状況が違うと便利です – goji

8

、私は通常、これは最も簡単なラムダで行われる見つける:

std::shared_ptr<Object> o; 
auto ftncall = [o](){ if (o) o->function(); } 
ftncall(); 

あなたは型消去が必要な場合は、単にstd::function<void()>にそれを詰め込みます。

C++ 11のLambdasは、ライブラリ関数に頼ることなく、bindと同じ仕事をすることができます。私は個人的にはもっと読みやすくしています。

bindはC++ 11でより良い仕事をすることができますが、この時点でコーナーケースです(C++ 1yでは、より多くのコーナーも切り捨てられます)。

+0

好奇心をそそらえて、いくつかの例を見せてもらえますか?std :: bindはC++ 11のほうがいいですか?多態性ラムダの欠如に関連していますか? – Sungmin

+1

@Sungmin 'bind'は完全な転送をサポートしていますが、ラムダはサポートしていません。ラムダは多態的ではありませんが、バインドは可能です。ラムダには固定戻り値の型があります:複数の多重定義を持つファンクタを渡すと 'bind'が変わる可能性があります。 'bind'は変数のファンクタのラッピングをサポートし、残ったvariadicはラムダをサポートしません。 'bind'は、' decltype'のような評価されていないコンテキストで呼び出すことができます。 'auto foo() - > decltype(bind(blah))'のために便利です:型は鈍いですが、labmdaのような魔法ではありません。それらは私の頭の上から私が考えることができるものです。それらの半分以上がC++に移行しました1y。 – Yakk

+0

また、これは信じられないほど役に立ちます - これはあなたの言うように「より簡単に思えますが、多態関数を使用する場合には 'bind'を使用する必要があることを知っておきましょう。おそらく、少なくとも私には問題がある。 –

関連する問題