2013-08-21 14 views
6

Wraz z nadejściem C++ 11, mamy unordered_map.cbegin/cend, aby konkretnie zwrócić nam wartości const_iterator. więc wyprowadzonym typem "it" w wyrażeniu "auto it = unordered_map.cbegin()" jest const_iterator.Oddany typ "auto it = unordered_map.find (key)"?

Jednakże, jeśli chodzi o funkcję unordered_map.find (key), myślę, że może brakować odpowiednika "cfind()", który zwraca konkretnie const_iterator.

Niektórzy mówią, że możemy użyć "const auto it = unordered_map.find (key)", aby uzyskać "const iterator", ale mam silne podejrzenie, że "const iterator" to ten sam "const_iterator", gdzie " const iterator "ogranicza możliwość zmiany samego iteratora, a" const_iterator "ogranicza możliwość zmiany zawartości, do której odwołuje się iterator.

Tak naprawdę, jeśli chcemy skorzystać z „auto” typu odliczenia pełnego (z wiedzy o niejasności lub odmiany typu „auto” dedukcji - Auto, Auto &, const auto &, itd.) , jak mogę mieć unordered_map.find (key), aby zwrócić "const_iterator" bez konieczności jawnego określenia "const_iterator" - to po wszystkim najlepszy przypadek użycia dla auto!

Poniżej znajduje się prosty przykład kodu, który demonstruje zachowanie kompilatora:

#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

Na czym polega pytanie? –

+0

Pytanie jest w czwartym akapicie: ** w jaki sposób mogę mieć unordered_map.find (key), aby zwrócić "const_iterator" bez konieczności jawnego określenia "const_iterator"?** – dfan

Odpowiedz

2

jestem nie zdaje sobie sprawy z żadnego miejsca, które zajmuje const_iterator, gdzie nie można po prostu przekazać iterator zamiast tego, więc ten brak może nie kolidować z codziennym pisaniem kodu. Jednak wolę używać const_iterator s (i ogólnie: const) wszędzie tam, gdzie nie potrzebuję mutowania, w interesie ogólnej komunikacji, więc myślę, że dodanie cfind() może być użytecznym dodatkiem do przyszłej biblioteki standardowej.

myślę, że ten kod może funkcjonować jako proste obejście, co próbujesz osiągnąć, choć:

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

Jest to prosta funkcja odlewania wrapper, podobne w stylu do move() i forward<T>(), aby zapewnić (i dokumentuj) ograniczenie indywidualnych zastosowań obiektu. Następnie można go używać tak:

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

ten może być również stosowany zamiast opierając się na cbegin() i cend(). Albo, może być stosowany w zakresie opartej na pętlach:

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

W powyższym przykładzie pętli, chociaż ja generalnie wolę auto const &element : ... wierzę, byłoby niepotrzebne i element nadal wywnioskować być const odniesienia .

+1

Masz rację, że nie napotkam żadnych problemów w moim codziennym kodowaniu, ale na konsekwencję i ogólną poprawność do komunikacji (i mogę być nadmiernie perfekcyjny w pisaniu kodu stylu C++ 11/14), cfind byłoby wspaniale mieć funkcję. Całkowicie zgadzam się, że opakowanie use_as_const wykonuje zadanie, * ale * funkcja jest bardziej sensowna, jeśli jest w standardzie, a nie dodawana przez użytkownika jako podstawa (mam nadzieję, że ma to sens). :) – Dejavu

+1

Jednak w zakresie opartym na przypadku, use_as_const ma sens bardziej semantyczny niż "znajdź". – Dejavu

1

To trochę niedoboru; mamy cbegin i cend ale bez odpowiedniego cfind itp

Sugeruję użyciu funkcji użytkowej, aby uzyskać const odwołanie do obiektu, jak na odpowiedź na 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

Powinien to być 'const T & as_const (const T & t)', więc można go zastosować do czegoś, co jest już const bez zgłaszania błędu. –

+0

@ChrisDodd w takim przypadku 'T' zostanie wydedukowane do' const U', więc nie ma błędu. – ecatmur