2013-08-21 44 views
6

隨着C++ 11的出現,我們有了unordered_map.cbegin/cend來專門返回const_iterator的值。所以在表達式「auto it = unordered_map.cbegin()」中推導出的'it'類型是const_iterator。但是,當涉及到unordered_map.find(key)函數時,我認爲可能會缺少一個「cfind()」對象,它會專門返回一個const_iterator。有人說我們可以使用「const auto it = unordered_map.find(key)」來獲得一個「const iterator」,但是我強烈懷疑「const iterator」是相同的「const_iterator」,其中「 const iterator「限制了更改迭代器本身的能力,而」const_iterator「限制了更改迭代器所引用內容的能力。因此,如果我們想充分利用「自動」類型演繹(瞭解混淆或「自動」類型演繹的變化 - 自動,自動&,常量自動&等)的優勢, ,我怎麼能讓unordered_map.find(key)返回一個「const_iterator」,而我不必顯式地指定「const_iterator」 - 這是所有最好的用例!演繹「auto it = unordered_map.find(key)」的類型?

以下是一個演示編譯器行爲的簡單示例代碼:

#include "stdafx.h" 
#include <unordered_map> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    typedef std::unordered_map<int, int> umiit; 
    umiit umii; 

    auto it0 = umii.find(0); 
    it0->second = 42; 
    const auto it1 = umii.find(0); 
    it1->second = 42; 
    umiit::const_iterator it2 = umii.find(0); 
    it2->second = 42; // expected compiler error: assigning to const 

    return 0; 
} 
+0

有什麼問題? –

+0

問題出現在第四段中:**我怎樣才能讓unordered_map.find(key)返回一個「const_iterator」而不必顯式指定「const_iterator」?** – dfan

回答

2

我不知道任何需要const_iterator的地方,而不是簡單地通過iterator來代替,所以這個缺陷可能不會影響日常代碼編寫。但是,爲了一般通信的利益,我更喜歡使用const_iterator(通常爲const),所以我認爲增加一個cfind()可能是未來標準庫的有用補充。

我覺得這個代碼可以作爲一個簡單的解決方法你要實現什麼功能,但:

template<typename T> 
auto use_as_const(T const &t) -> T const & { 
    return t; 
} 

這是一個簡單的鑄件的包裝功能,風格類似move()forward<T>(),提供(並記錄)該對象的個別用法的約束。然後,您可以使用這樣的:

auto it1 = use_as_const(umii).find(0); 

這也可以用來代替扶着cbegin()cend()。基於範圍的,或者它可以在用於循環:

for (auto &element : use_as_const(some_vector_of_string)) { 
    cout << element; 
    // element = ""; // This line shouldn't compile. 
} 

在上面循環例子,雖然我一般喜歡auto const &element : ...,我相信這將是不必要的,element仍然會被推斷爲const引用。

+1

你說得對,我在日常編碼中沒有遇到任何問題,但是爲了一致性和常規的正確通信(我在編寫C++ 11/14樣式代碼時可能過於完美), cfind將是一個很棒的功能。我完全同意use_as_const包裝器可以完成這項工作,但是*如果功能是在標準中,而不是由用戶添加樣板文件(希望這是有道理的),那麼這個特性真的更有意義。 :) – Dejavu

+1

但是,在基於情況的範圍內,use_as_const確實比「find」更有語義意義。 – Dejavu

1

這是一個有點缺陷的;我們有cbegincend,但沒有相應的cfind

我建議使用效用函數來獲得一個const對象的引用,按照答案forcing use of cbegin()/cend() in range-based for

template<typename T> constexpr const T &as_const(T &t) { return t; } 

auto it1 = as_const(umii).find(0); 
it1->second = 42; // fails 
+1

它應該是'const T&as_const(const T&t)',所以它可以應用於已經是const的東西,而不會標記錯誤。 –

+0

@ChrisDodd在這種情況下'T'被推斷爲'const U',所以沒有錯誤。 – ecatmur