2016-07-12 5 views
0

switch文では、それ以外の場合はデフォルトの戻り値を指定できます。 私はstd :: mapと同様のことをしたいと思いますが、可能かどうかはわかりません: map :: endの代わりに特定の値/エントリを返すようにすることはできますか? ?マップエントリが見つからなかった場合は、map :: endではなく特定のマップエントリを返します。

例は、(ここで私はultimativelyやってみたいものです - 私は、コードが動作しないことを認識しています):そのような

std::map<std::string, void* (*) (DataObject*)> commands; //Mapping functions to keys 
commands["Test"] = function(DataObject d){doSomething();} 
commands[Nothing else applies] = function(DataObject d){doSomethingElse();} 

commands.find("Test")(someDataObject); // doSomething(); happens 
commands.find("blabla")(someDataObject); //doSomethingElse(); happens because no other entry was found 

なりの何かが可能?

(また、私はこの例では関数ポインタを使用している方法は、おそらくすべてでは動作しません - 私は私が何をしたい達成するためにcpp11のラムダ式を使用することはできますか?)

を私はしたくありませんswitch節を使用したり、if(m.find(x) != m.end())節を必要としたり、if-elseをさらに必要としません。

答えて

0

デフォルト値を使用して独自のファンクタを使用することができます。

struct MyFunctor: public std::function<void(DataObject*)> { 

    template <typename F> 
    MyFunctor (F &&f) : std::function<void(DataObject*)> (std::forward<F> (f)) { } 

    MyFunctor() : std::function<void(DataObject*)> (doSomethingElse) { } 

}; 

doSomethingElseと仮定すると、すでに定義された関数です。その後

あなたは、単に行うことができます。

std::map<std::string, MyFunctor> commands; //Mapping functions to keys 
commands["Test"] = [] (DataObject *) { }; // Assign from lambda 

DataObject *myDataObject= new DataObject(); 
commands["Not Defined"] (myDataObject); // Call doSomethingElse 

あなたは簡単にテンプレートを使用して(コンパイル時に定義された)異なるデフォルト値を持つことができMyFunctorのために:

template <void (*DefaultFn) (DataObject*)> 
struct MyFunctor: public std::function<void(DataObject*)> { 

    template <typename F> 
    MyFunctor (F &&f) : std::function<void(DataObject*)> (std::forward<F> (f)) { } 

    MyFunctor() : std::function<void(DataObject*)> (DefaultFn) { } 

}; 

std::map<std::string, MyFunctor<doSomethingElse>> commands; 
+0

うわー、これは素晴らしいよ、ありがとう!私はちょうど今、それを本当に理解しなければならないだろう、笑。 (Javaのバックグラウンドから来て、C++の多くのものはまだ新しくなっています) – user2065501

+0

この場合「&&」の意味を教えていただけますか?私はそれがRValueの略であることを読みましたが、私はこの状況でそれを利用していません。また、「上書き」作業はどのくらい正確に行われますか(定義ごとに、マップ内の各キーの値はMyFunctorタイプにする必要がありますが、コードはラムダで単純に上書きできますが、どれがうまくいくのですか? ) - 待ち、nvm、それはMyFunctorが関数から継承するためですだから我々はラムダを渡すとき、MyFunctorはそのラムダで構築され、次にフォワードメソッドを呼び出しますか?最後の1つ:なぜクラスの代わりに構造体ですか? – user2065501

+0

@ user2065501 '&&'は[universal reference](https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers)です。これは、左辺値または右辺値を取ることができることを意味します。完璧なフォワーディングを行います(このコードでは心配する必要はありません)。このコードは、 'std :: function'のコンストラクタに渡すことができるものを使って' MyFunctor'を構築することができます(ラムダを割り当てると、 'MyFunctor'を作成します。与えられたラムダは単に親 'std :: function'に渡します)。 'class'の代わりに' struct'を使うのはちょうど習慣です。もし望むなら 'class'を使います。 – Holt

0

んが、あなたがすることはできませんその機能がstd::mapstd::map::find()の場合、キーが見つからない場合にはend()と等しい反復子を返しますそれを起こす。したがって、if(m.find("blah") == m.end())節を使用するか、std::mapという別のものを使用するか、必要な機能を持つ独自のクラスを作成する必要があります。

デフォルト状態に必要な機能があり、それにはstd::map::operator[]ではなくstd::map::find()でアクセスする特殊な値の型があるかもしれませんが、副作用があります。検索したキーごとにマップに追加されます。私はそれが1つのif()句を持つよりも良い解決策であるとは思っていませんが、それはあなた次第です。

関連する問題