2013-08-21 13 views
6

Mit dem Aufkommen von C++ 11 haben wir unordered_map.cbegin/cend, um speziell Werte von const_iterator zurückzugeben. Der abgeleitete Typ von "it" im Ausdruck "auto it = unordered_map.cbegin()" ist also const_iterator.Abgeleitete Art von "auto it = unordered_map.find (key)"?

Allerdings, wenn es um unordered_map.find (Schlüssel) -Funktion geht, denke ich, es fehlt möglicherweise ein "cfind()" Gegenstück, die spezifisch einen const_iterator zurückgibt.

Einige sagen, dass wir "const auto it = unordered_map.find (key)" verwenden können, um einen "const iterator" zu erhalten, aber ich habe den starken Verdacht, dass "const iterator" gleich "const_iterator" ist, wobei " const iterator "beschränkt die Möglichkeit, den Iterator selbst zu ändern, während" const_iterator "die Möglichkeit einschränkt, den Inhalt zu ändern, auf den sich der Iterator bezieht.

Also, wirklich wollen, wenn wir die Vorteile von „auto“ Typ Abzug (mit dem Wissen über die Verwirrungen oder die Variationen von „auto“ Typ Abzug - auto, auto &, Konst Auto &, etc.) vollständig zu übernehmen , wie kann ich unordered_map.find (key) haben, um einen "const_iterator" zurückzugeben, ohne dass ich explizit "const_iterator" angeben muss - das ist nach all dem besten Anwendungsfall für auto!

Unten ist ein einfaches Beispiel-Code, der den Compiler Verhalten zeigt:

#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

Was ist die Frage? –

+0

Die Frage ist im vierten Absatz: ** Wie kann ich unordered_map.find (Schlüssel) haben, um einen "const_iterator" zurückzugeben, ohne dass ich explizit "const_iterator" angeben muss?** – dfan

Antwort

2

Ich bin nicht bewusst, dass ein Ort, der eine const_iterator nimmt, wo Sie nicht einfach eine iterator übergeben könnte, so dass dieser Mangel nicht viel stören mit dem täglichen Schreiben von Code. Ich bevorzuge jedoch die Verwendung von const_iterator s (und const im Allgemeinen), wo ich im Interesse der allgemeinen Kommunikation nicht mutieren muss, daher denke ich, dass das Hinzufügen einer cfind() eine nützliche Ergänzung zur zukünftigen Standardbibliothek sein könnte.

Ich denke, dieser Code als einfache Abhilfe funktionieren konnte für das, was Sie versuchen, wenn auch zu erreichen:

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

Dies ist eine einfache Guss Wrapper-Funktion, ähnlich in der Art move() und forward<T>(), zur Verfügung zu stellen (und dokumentieren) eine Einschränkung für die einzelnen Nutzungen des Objekts. Man könnte es dann wie folgt verwenden:

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

Dies auch statt stützte sich auf cbegin() und cend() verwendet werden könnten. Oder es könnte verwendet werden in bereichsbasierte for-Schleifen:

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

In dem obigen Schleife Beispiel, obwohl ich in der Regel auto const &element : ... vorziehen würde, ich glaube, es wäre unnötig und element würde immer noch geschlossen werden eine konstante Referenz zu sein .

+1

Sie haben Recht, dass ich in meinem täglichen Programmieren keine Probleme hatte, aber aus Gründen der Konsistenz und allgemeinen Korrektheit für die Kommunikation (und ich könnte beim Schreiben von C++ 11/14-Code übermäßig perfektioniert sein), cfind wäre ein tolles Feature. Ich stimme völlig zu, dass der use_as_const-Wrapper die Aufgabe erledigt, * aber * das Feature ist wirklich sinnvoller, wenn es im Standard ist, anstatt das Boilerplate vom Benutzer hinzuzufügen (hoffe, das macht Sinn). :) – Dejavu

+1

In dem Bereich, der für case basiert, macht use_as_const jedoch mehr semantischen Sinn als der "find" -Eintrag. – Dejavu

1

Es ist ein bisschen ein Mangel; wir haben cbegin und cend aber keine entsprechenden cfind usw.

Ich würde vorschlagen, eine Nutzenfunktion unter Verwendung eines const Verweis auf das Objekt zu erhalten, gemäß der Antwort auf 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

Es sollte "const T & as_const (const T & t)" sein, also kann es auf etwas angewendet werden, das bereits const ist, ohne einen Fehler zu melden. –

+0

@ChrisDodd in diesem Fall wird "T" zu "const U" abgeleitet, also gibt es keinen Fehler. – ecatmur