2013-03-20 11 views
7

Jeśli mam zasięg (para 2 iteratorów), istnieje sposób napisania pętli "dla każdego", która wykorzystuje zakres, a nie surową tablicę lub kontener.Może pracować w oparciu o zakres dla pętli w zakresie

coś takiego:

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

Czy możesz użyć wzmocnienia? – inf

+1

Jeśli możesz użyć boost, boost ma iterator zakresu. – OmnipotentEntity

+0

Tak, mogę i robię :) <3 boost – NoSenseEtAl

Odpowiedz

13

Zgodnie z Why was pair range access removed from C++11? można użyć adaptera np. as_range w przyjętym odpowiedź boost::make_iterator_range lub napisać własne:

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)) 
    ... 

Powodem tego nie stosuje się w ogóle jest to, że za Alastair Meredith's paper, algorytmów,

  • mismatch i partition_copy powrotnym para iteratorów z różnych zakresów;
  • zwraca parę obiektów, które w ogóle nie mogą być iteratorami, a jeśli są, to nie ma gwarancji, że tworzą zakres;
  • minmax_element może powrócić do zakresu, ale może także zwrócić odwróconej zakresu (np odwracalnej sortowanych zakresie minmax_element powróci {prev(last), first};.
  • equal_range gwarantuje zwróci wybór
+0

Czy wiesz, jakie funkcje zwracają nieprawidłowy zakres? Mam na myśli std, a nie śmieci użytkowników: P – NoSenseEtAl

+0

@NoSenseEtAl dobre pytanie, patrz wyżej. – ecatmur

2

Nie sądzę, to będzie działać tak po wyjęciu z pudełka, co equal_range zwraca parę iteratorów while, for cyklu nad zakresem według documentation są:

The begin_expr and end_expr are defined to be either: 
If (__range) is an array, then (__range) and (__range + __bound), where __bound is the array bound 
If (__range) is a class and has either a begin or end member (or both), then begin_expr is __range.begin() and end_expr is __range.end(); 
Otherwise, begin(__range) and end(__range), which are found based on argument-dependent lookup rules with std as an associated namespace. 

Powiedziałbym, że możesz zdefiniować funkcje begin i end, które zajmują parę iteratorów i zwracają pierwszą i drugą ponownie.

0

Co std::equal_range powraca jest po prostu std :: pair.Norma nie obejmuje żadnej metody do iteracji takich rzeczy.Alternatywnie nie obejmuje żadnej metody iteracji nad takimi rzeczami.

Co można przeczytać jest prezentacjaAlexandrescu Here is the video. Doskonały odczyt na bardziej el egant sposób iteracji pojemników za pomocą zakresów.

Zakresy są realizowane w jego bibliotece Loki.

+0

zakresy są zaimplementowane w boost i są na dobrej drodze do std, więc każdy, kto zechce ich użyć powinien użyć boosta – NoSenseEtAl

+0

Jestem świadomy Boost.Range jednak nie spojrzałam na to dobrze, nie byłam pewna jeśli są takie same jak Zakresy Alexandrescu. Dlatego nie sugerowałem Boost.Range. Jesteś pewien, że to to samo? –

+0

afaik nie, ale idk różnica, jeśli Iirc corectly boost/std zakresy są tylko parami iters .... ale ja naprawdę nie znam szczegółów ... – 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; 
    } 
} 
Powiązane problemy