2016-07-12 46 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的lambda表達式來完成我想做什麼?)

我不想使用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,但在這種情況下我沒有得到它的使用。另外,「覆蓋」究竟是如何工作的(Per定義,映射中每個鍵的值應該是MyFunctor類型的,但代碼允許用lambda簡單地覆蓋它 - 這是好的,但它是如何工作的? ) - 等等,nvm,這是因爲MyFunctor繼承了函數,對吧?所以,當我們傳遞一個lambda時,MyFunctor會使用該lambda構造,然後調用forward方法?最後一個:爲什麼要結構而不是類? – user2065501

+0

@ user2065501'&&'是[通用參考](https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers),這意味着它可以取左值或右值並且做完美的轉發(你不應該在這段代碼中擔心)。這樣的代碼允許你使用任何可以傳遞給'std :: function'構造函數的構造函數來構造'MyFunctor',這是一個lambda表達式(當你分配一個lambda表達式時,你創建一個新的'MyFunctor'給定的lambda,它只是將它傳遞給它的父'std :: function')。 'struct'而不是'class'只是習慣,如果你願意,可以使用'class'。 – Holt

0

不,你不能有與std::map作爲std::map::find()功能返回迭代器等於end()當密鑰找不到,你不能deref這就是它。所以你要麼需要使用if(m.find("blah") == m.end())子句,要麼使用別的東西,或者用你需要的功能編寫自己的類。

雖然您可能有特殊的價值類型,但默認狀態將具有您需要的功能,然後通過std::map::operator[]而不是std::map::find()訪問它,但會產生副作用 - 對於您搜索的每個鍵,新條目都將添加到地圖中。我懷疑這會比擁有一個if()條款更好的解決方案,但這取決於您。