2013-03-20 9 views
30

Diese Frage bezieht sich auf:Verwendung CBEGIN Zwingen()/CEND() in bereichsbasierte für

When should I use the new ranged-for and can I combine it with the new cbegin/cend?

Basierend auf diese Frage, die Verwendung von cbegin() und cend() zu zwingen, muss man tun Beispiel:

for (auto& v: const_cast<decltype(container) const>(container)) 

Das ist eine Menge Standardcode für ein Konstrukt, das es beseitigen sollte. Gibt es einen kompakteren Weg dies zu tun? Der Grund für meine Frage ist, dass ein implizit geteilter Container meine Verwendung von begin() als einen Anhaltspunkt dafür, sich zu lösen, verwenden könnte.

+3

Die fored-for-Schleife wurde für die Bequemlichkeit hinzugefügt, nicht als Ersatz für die bestehende for-Anweisung. Vielleicht ist dies ein Fall, in dem die alte for-Schleife nützlicher ist? –

+0

Sie wollen wahrscheinlich 'declltype ((container))', um eine Referenz zu erhalten. – ecatmur

+3

Sie können einfach "const auto & v" eingeben. –

Antwort

26

Update: std::as_const wird im <utility> Header in C++ 17, sein.

Vor C++ 17 gibt es keine integrierte Syntax dafür; Sie können jedoch leicht eine Bequemlichkeit Wrapper schreiben:

template<typename T> constexpr const T &as_const(T &t) noexcept { return t; } 
for (auto &v: as_const(container)) 

Beachten Sie, dass diese Anrufe begin() const statt cbegin() speziell; die Standard container general requirements spezifizieren, dass cbegin() und begin() const sich identisch verhalten.

Wenn Ihr Behälter behandelt nicht konstante Iteration speziell, könnte es sinnvoll sein, für sie selbst eine Member-Funktion haben:

const Container &crange() const noexcept { return *this; } 
for (auto &v: container.crange()) 
+1

Ich denke, du hättest den 'constexpr'-Spezifizierer deinem 'as_const()' -Trick voranstellen sollen. – user1095108

+0

@ user1095108 danke, gute Idee. – ecatmur

+0

@ user1095108, warum braucht man dort "constexpr"? Der Inhalt des Containers kann sich ändern. – Yola

11
const auto& const_container = container; 

for (const auto& v: const_container) { 
+3

Wo 'Typ' geschrieben wird' auto'? –

+0

@BenVoigt Danke, ich habe die Verwendung von 'auto' für die Containerreferenz geändert und den Namen auch ein wenig verbessert. –

+0

Ich schlage vor, explizit '& v' für zusätzliche Klarheit zu qualifizieren. – Boinst

2

Die bereichsbasierte for-Schleife nie verwendet cbegin() oder cend(). (Deshalb gibt es keine Möglichkeit, es zu erzwingen.) Es gibt erstaunlich viele Gerüchte, die das Gegenteil beweisen; einige glauben, dass cbegin() und cend() verwendet werden, aber nie versuchen, ob der gleiche Code ohne begin() und end() kompilieren würde. Ein triviales Beispiel folgt. Vermutlich werden nur begin und end ausgedruckt, egal wie viele const_cast s hinzugefügt werden.

#include <iostream> 

class Iterable { 
    struct Iterator { 
    bool operator !=(const Iterator &) { return false; } 
    int operator *(){ return 0; } 
    Iterator& operator ++() { return *this; } 
    }; 
public: 
    Iterator cbegin() const noexcept { 
    std::cout << "cbegin" << std::endl; 
    return Iterator{}; 
    } 
    Iterator cend() const noexcept { 
    std::cout << "cend" << std::endl; 
    return Iterator{}; 
    } 
    Iterator begin() const noexcept { 
    std::cout << "begin" << std::endl; 
    return Iterator{}; 
    } 
    Iterator end() const noexcept { 
    std::cout << "end" << std::endl; 
    return Iterator{}; 
    } 
}; 

int main() { 
    Iterable a; 
    const Iterable b; 
    for (auto i : a) {} 
    for (auto i : b) {} 
    for (const auto &i : a) {} 
    for (const auto &i : b) {} 
    return 0; 
} 
+0

viele (alle) wissen genug, um zu wissen, dass ein Aufruf von .'begin() 'auf einem Const-Container dem Aufruf von' cbegin() ' – user1095108

+1

entspricht Nein, ist es nicht. Ganz einfach, weil es Ihnen freisteht, eine Implementierung von 'cbegin()' vollständig anderer Form 'begin()' zu liefern, wenn Sie sich so entscheiden. Der Kernpunkt meiner Antwort: Die ursprüngliche Frage basiert auf einer falschen Annahme, dass die bereichsbasierte "for" -Schleife 'cbegin()' oder 'cend()' unter bestimmten Bedingungen aufruft. Tatsächlich tut es das nicht. Das ist alles. –

+0

Es macht normalerweise das Äquivalent, der Container ist const. – user1095108

Verwandte Themen