與所有C++庫決策一樣,存在一個哲學問題的根源。
在vector
,operator[]
定義爲常量和非常量的情況。這是明智的,因爲對於長度爲N的矢量,operator[](0...N-1)
將總是具有含義,無論是否爲const。該元素將存在。
以此爲基線,地圖應該做什麼?確定是否存在任何下標(鍵)沒有絕對的標準。
隨着可變的operator[]
,選擇默認構建元素是合理的 - 在所有調用者引用它後,他希望它存在,並且我們可以使它存在。這是最令人驚訝的道路。
現在怎麼樣的不可改變的情況?元素可能存在也可能不存在,如果不存在,我們不能改變地圖,因爲這會違反const
的精神。
我們也不應該拋出異常,因爲對於習慣於處理vector
的人來說,這可能會讓人感到意外,因爲在這種情況下不會出現任何異常(或可能!)。然後我們會看到兩個類似的接口,它們的行爲非常不一樣。
答案是根本不提供mutable operator []。開發人員(如你)可能會驚訝地發現它不存在,但他們有機會查看文檔並意識到他們正在吠叫錯誤的樹。
如上所述,我們有at()
(如果下標不存在,則拋出異常,如向量),我們有find()
。
與提升的幫助不大(很快,C++ 17),我們可以給自己一個效用函數:
#include <map>
#include <string>
#include <utility>
#include <type_traits>
#include <iostream>
#include <boost/optional.hpp>
template<class Map>
auto maybe_get_impl(Map& map, typename Map::key_type const& key)
{
using reference_type = std::conditional_t<
std::is_const<std::remove_reference_t<Map>>::value,
typename Map::mapped_type const&,
typename Map::mapped_type&>;
boost::optional<reference_type> result;
auto ifind = map.find(key);
if (ifind != map.end())
{
result = ifind->second;
}
return result;
}
template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A> const& map, K const& key)
{
return maybe_get_impl(map, key);
}
template<class K, class V, class Comp, class A>
auto maybe_get(std::map<K, V, Comp, A>& map, K const& key)
{
return maybe_get_impl(map, key);
}
int main()
{
std::map<int, std::string> mymap;
mymap.emplace(1, "hello");
mymap.emplace(2, "world");
// note: non-const because we're taking a reference from a mutable map;
std::string part = std::string("goodbye, cruel world");
std::cout << maybe_get(mymap, 1).value_or(part) << std::endl;
std::cout << maybe_get(mymap, 2).value_or(part) << std::endl;
std::cout << maybe_get(mymap, 0).value_or(part) << std::endl;
}
預期輸出:
hello
world
goodbye, cruel world
你試過'CBEGIN() '? –
_「原因是因爲operator []不是const?」_是的,請看[這裏](http://en.cppreference.com/w/cpp/container/map/operator_at)。 –