2013-03-20 8 views
7

Wenn ich Bereich (Paar von 2 Iteratoren) habe, gibt es eine Möglichkeit, "für jede" Schleife zu schreiben, die Bereich verwendet, nicht ein RAW-Array oder Container.Kann bereichsbasierte für Schleifenarbeit über einen Bereich

Etwas wie folgt aus:

auto rng = std::equal_range(v.begin(),v.end(),1984); 
for(const auto& elem: rng) { 
    // ... 
} 
+1

Können Sie Boost verwenden? – inf

+1

Wenn Sie Boost verwenden können, hat Boost einen Bereichsiterator. – OmnipotentEntity

+0

ja ich kann, und ich mache :) <3 boost – NoSenseEtAl

Antwort

13

Gemäß Why was pair range access removed from C++11? können Sie einen Adapter verwenden, z. die as_range an der akzeptierte Antwort, boost::make_iterator_range, oder schreiben Sie Ihre eigene:

template<typename It> struct range { 
    It begin_, end_; 
    It begin() const { return begin_; } 
    It end() const { return end_; } 
}; 
template<typename It> range<It> as_range(const std::pair<It, It> &p) { 
    return {p.first, p.second}; 
} 

auto rng = std::equal_range(v.begin(),v.end(),1984); 
for(const auto& elem: as_range(rng)) 
    ... 

Der Grund, warum dies nicht anwendbar ist im Allgemeinen ist, dass pro Alastair Meredith's paper, der Algorithmen,

  • mismatch und partition_copy Rückkehr ein Paar Iteratoren aus verschiedenen Bereichen;
  • minmax gibt ein Objektpaar zurück, das möglicherweise gar kein Iterator ist, und wenn es keine gibt, gibt es keine Garantie, dass sie einen Bereich bilden;
  • minmax_element kann einen Bereich zurück, aber es kann auch einen umgekehrten Bereich (zB auf einem Reverse-sortierten Bereich minmax_element zurück {prev(last), first} zurückkehren;.
  • equal_range garantierte eine Reihe zurück
+0

wissen Sie, welche Funktionen ungültigen Bereich zurückgeben? Ich meine in std, nicht user junk: P – NoSenseEtAl

+0

@NoSenseEtAl gute frage, siehe oben. – ecatmur

2

glaube ich es nicht so aus der Box als equal_range gibt ein Paar von Iteratoren arbeiten, während der für den Zyklus über Bereich documentation nach sind:

Ich würde sagen, Sie können definieren begin und end Funktionen, die das Paar von Iteratoren nehmen und erste und zweite jeweils zurückgeben.

0

Welche std::equal_range Renditen ist einfach ein std :: pair. Der Standard deckt keine Methode, um über solche Dinge zu iterieren.

Was Sie lesen möchten, ist Alexandrescus "Iterators must go" Präsentation.Ein ausgezeichnetes Lesen auf einem mehr el. Here is the video Möglichkeit, Container über Bereiche zu iterieren.

Bereiche sind in seiner Loki Bibliothek implementiert.

+0

Bereiche sind in Boost implementiert und sie sind auf dem Weg zur Standard, so dass jeder, der sie verwenden möchte, Boost verwenden sollte – NoSenseEtAl

+0

Ich bin mir bewusst, Boost.Range aber ich habe nicht einen ganz guten Blick darauf, war mir nicht sicher wenn sie die gleichen sind wie Alexandrescus Ranges. Deshalb habe ich Boost.Range nicht vorgeschlagen. Bist du sicher, dass sie dasselbe sind? –

+0

afaik nein, aber IDK der Unterschied, wenn iirc correct Boost/Std-Bereiche sind nur Paare von iters .... aber ich weiß wirklich nicht die Details ... – NoSenseEtAl

0
#include <vector> 
#include <algorithm> 
#include <iostream> 

template <typename I> 
struct range_adapter { 
    std::pair<I, I> p; 

    range_adapter(const std::pair<I, I> &p) : p(p) {} 

    I begin() const { return p.first; } 
    I end() const { return p.second; } 
}; 

template <typename I> 
range_adapter<I> in_range(const std::pair<I, I> &p) 
{ 
    return range_adapter<I>(p); 
} 

int main() 
{ 
    std::vector<int> data { 1, 2, 2, 3, 3, 3, 4 }; 

    auto r = std::equal_range(data.begin(), data.end(), 2); 

    for (const auto &elem : in_range(r)) 
    { 
     std::cout << elem << std::endl; 
    } 
} 
Verwandte Themen