Erste Frage: Ist es möglich, einen const_iterator
mit "auto" zu erzwingen? Zum Beispiel:
map<int> usa;
//...init usa
auto city_it = usa.find("New York");
Ich möchte nur abfragen, anstatt irgendetwas zu ändern, auf das city_it
gerichtet ist. Ich möchte, dass city_it
map<int>::const_iterator
ist. Bei Verwendung von auto ist city_it
jedoch gleich dem Rückgabetyp von map::find()
, der map<int>::iterator
ist. Irgendein Vorschlag?
Sorry, aber ich denke, der beste Vorschlag ist nicht mit auto
, da Sie eine (implizit gültige) Typkonvertierung durchführen möchten. auto
dient zum Ableiten von genauer Typ, was hier nicht gewünscht ist.
Schreib es einfach so:
std::map<std::string, int>::const_iterator city_it = usa.find("New York");
Wie von MooingDuck richtig hervorgehoben, kann die Verwendung von Typ-Aliasnamen die Lesbarkeit und Wartbarkeit Ihres Codes verbessern:
typedef std::map<std::string, int> my_map;
my_map::const_iterator city_it = usa.find("New York");
Dies ist keine drastisch andere Herangehensweise an die Konvertierung in const
im Vergleich zu der Antwort von @ Jollymorphic, aber ich denke, dass es nützlich ist, eine solche Einzeilerfunktion zu haben:
template<class T> T const& constant(T& v){ return v; }
Das macht die Umwandlung für das Auge viel attraktiver:
auto it = constant(usa).find("New York");
// other solutions for direct lengths comparision
std::map<std::string, int>::const_iterator city_it = usa.find("New York");
auto city_it = const_cast<const std::map<std::string, int>&>(usa).find("New York");
Nun, ich würde sagen, größer ist nicht immer besser. Sie können natürlich den Namen der Funktion nach Ihren Wünschen wählen - as_const
oder nur const_
sind mögliche Alternativen.
Eine andere Variante, die auto verwendet (beides ein veränderliches usa und ein const usa beibehalten):
map<std::string, int> usa;
//...init usa
const auto &const_usa = usa;
auto city_it = const_usa.find("New York");
Wenn die Karte nach init überhaupt nicht veränderbar sein muss, gibt es einige andere Optionen.
sie können usa als const definieren und mit einem Funktionsaufruf initialisieren:
const map<std::string, int> usa = init_usa();
auto city_it = usa.find("New York");
oder ein Lambda verwenden, um eine const-Map zu initiieren:
const auto usa = [&]()->const map<std::string, int>
{
map<std::string, int> usa;
//...init usa
return usa;
}();
auto city_it = usa.find("New York");
Eine saubere Lösung ist, mit einer const - Referenz auf die ansonsten änderbare Karte zu arbeiten:
const auto &const_usa = usa;
auto city_it = const_usa.find("New York");
Damit stellen Sie sicher, dass Sie const_usa
nicht ändern können, und verwenden Iteratoren.
Seit C++ 17 können Sie std::as_const
wie folgt verwenden:
#include <utility>
// ...
auto city_it = std::as_const(usa).find("New York");
Ich bin nicht in der Lage, dies jetzt zu testen, aber ich denke, dass es den Trick erfüllt:
auto city_it = const_cast< const map<int> & >(usa).find("New York");
In C++ 11 können Sie Folgendes tun:
decltype(usa)::const_iterator city_it = usa.find("New York");