2017-02-16 9 views
2

Manchmal möchte ich den Iterator verwenden, der von einer Funktion aus der Algorithmusbibliothek zurückgegeben wird. Das Problem, dem ich gegenüberstehe, tritt auf, wenn ich zwischen einer modifizierenden Funktion und einer nicht modifizierenden Funktion gehe. Ursache in der nicht-modifizierenden Funktion möchte ich eine const_iterator verwenden. Als Spielzeug Beispiel:Gibt es einen make_const_iterator?

vector<int> v = { 1, 8, 7, 4, 3, 6, 2, 5 }; 
auto it = partition(begin(v), end(v), bind(greater<int>(), placeholders::_1, 3)); 

cout << (find(cbegin(v), it, 13) != cend(v)) << endl; 

Wenn ich versuche, diesen Code zu kompilieren, erhalte ich die Fehlermeldung:

no matching function for call to find(std::vector<int>::const_iterator, __gnu_cxx::__normal_iterator<int*, std::vector<int> >&, int)

Das Problem, das ich in laufenden bin ist der einzige Konvertierungsprozess I ist möglicherweise teuer finden: auto cit = next(cbegin(v), distance(begin(v), it))

Gibt es eine Möglichkeit, dass dies funktioniert? Oder bin ich fest, umwandeln oder einfach nicht verwenden const_iterator s?

+0

Nur ein preemptives Kommentar, ich weiß, dass ich nur 'find' direkt auf' v' nutzen könnte. Ich suche keinen besseren Weg, um mein Spielzeugbeispiel zu schreiben. Ich suche nach einer Lösung für das Problem, die es veranschaulicht. –

+0

Haben Sie versucht, nur einen Const_iterator aus dem normalen zu konstruieren? – rubenvb

+0

Sollen wir annehmen, dass der Typ des ursprünglichen Containers unbekannt ist? Wenn nicht, macht 'decltype (v) :: const_iterator (it)' den Trick. Die Verwendung von 'cvegin (v)' in Ihrer vorgeschlagenen Lösung scheint zu implizieren, dass Sie Zugriff auf 'v' haben und nicht nur auf den Iterator. –

Antwort

3

Es ist viel billiger, einfach den wandelbar Iterator auf einen konstanten Iterator zu Stimmen:

cout << (find(cbegin(v), vector<int>::const_iterator{it}, 13) 
     != cend(v)) << endl; 

A wandelbar Iterator immer gießbare in einen konstanten Iterator sein sollte.

EDIT: Ich fand den Teil des Standards, der garantiert, dass ein Iterator in einen konstanten Iterator konvertierbar ist.

Tabelle 96 in Abschnitt 23.2 "Container Anforderungen" legt fest, dass der Ausdruck X::iterator Ergebnisse in:

any iterator category that meets the forward iterator requirements. convertible to X::const_iterator.

+1

Gibt es eine solche Umwandlung? –

+1

@ Cheersandthth.-Alf Siehe hier: http://Stackoverflow.com/a/7759474/1294207 –

+1

@FantasticMrFox: Das ist fantastisch, danke. Ich vertraue dem guten Roboter. Aber ein Standard Ref. hätte die Sache erledigt. –

4

Sie das Template-Argument angeben:

find<decltype(cbegin(v))>(cbegin(v), it, 13) != cend(v) 

Demo

+2

Ich sehe den Fehler ist eigentlich weil ich Mehrdeutigkeit in der Vorlage Abzug von 'finden werde. Das ist das gleiche wie bei den anderen Beispielen, die einen Cast erzwingen. Gibt es irgendwo eine Aussage, dass ein solcher Cast legal ist und nicht nur eine Implementierung definiert? –

1

Es sind drei Ansätze.

Die erste ist

cout << (find(begin(v), it, 13) != cend(v)) << endl; 
       ^^^^^ 

Die zweite zu schreiben, ist

cout << (find(cbegin(v), static_cast<std::vector<int>::const_iterator>(it) 
, 13) != cend(v)) << endl; 

Oder kürzer

cout << (find(cbegin(v), static_cast<decltype(v.cbegin())>(it) 
, 13) != cend(v)) << endl; 

Und die dritte ist zu schreiben, schreiben

cout << (find<std::vector<int>>::const_iterator>(cbegin(v), it, 13) != cend(v)) << endl; 

oder kürzer

cout << (find<decltype(v.cbegin())>(cbegin(v), it, 13) != cend(v)) << endl; 
+0

Ja, ich erwähne in der Frage, dass ** 1 ** unerwünscht ist. Die anderen 2 Optionen sind beide effektiv zu einem "const_iterator" (was ich nicht wusste, dass Sie tun könnten). Gibt es etwas im Standard, das dies explizit erlaubt? –

+1

@ JonathanMee Siehe Tabelle 96 - Containeranforderungen die Zeile über Iteratoren. –