2013-03-25 31 views
21

Jeśli elementy w std::initializer_list są zawsze wartościami stałymi, dlaczego mamy metodę szablonową, taką jak begin()/end(), a nie cbegin()/cend()? Te nazwy (według konwencji, na przykład w porównaniu z np. std::vector) mogą sugerować, że zarówno metoda std::initializer_list może zwrócić iterator, kiedy zawsze zwracają const_iterator.std :: initializer_list bez cbegin()/cend()

+2

dobre pytanie. Dobra robota. –

+0

@LightnessRacesinOrbit Hej piękna, miło cię poznać tutaj :-) – Des1gnWizard

+0

@ Des1gnWizard: To nie jest serwis randkowy, dziękuję. –

Odpowiedz

25

Chociaż nie może zapewnić wgląd w przyczyny dlaczego cbegin() i cend() nie są częścią interfejsu std::initializer_list „s opróczbegin() i end(), są z pewnością dobre powody, dla których dwie ostatnie funkcje składowe powinny być tam.

Jednym powodem jest to, na przykład, że zasięg oparte for pętla jest zdefiniowana przez standard C++ 11 dokładnie pod względem funkcji begin() i end() (§ 6.5.4/1). Dlatego też, w celu umożliwienia używać go z listy initializer, std::initializer_list musi dostarczyć begin() i end() członków funkcje:

#include <utility> 
#include <iostream> 

int main() 
{ 
    auto l = { 1, 2, 3, 4, 5 }; 
    for (int x : l) // Works because std::initializer_list provides 
        // the member functions begin() and end(). 
    { 
     std::cout << x << " "; 
    } 
} 

Ponadto, warto wziąć pod uwagę, że funkcje składowe cbegin() i cend() nie były obecne przed C++ 11: dlatego posiadanie begin() i na interfejsie std::initializer_list pozwala na to, aby stare standardowe algorytmy napisane pod kątem begin() i end() działały również z listami inicjalizującymi, bez konieczności ich przepisywania.

Piszesz:

Nazwy te (konwencje, w porównaniu do np std::vector) może sugerować, że zarówno metoda std::initializer_listiterator mógł wrócić, kiedy zawsze wrócić const_iterator.

W rzeczywistości ta analogia nie jest odpowiednia. Funkcja std::vector jest begin() przykładowo zwraca iterator po uruchomieniu na non const wystąpienia std::vector (czyli zmienny jednym, którego elementy mogą być modyfikowane, dodane lub usunięte) i const_iterator po uruchomieniu na przykład const (tj. niezmienny, którego zawartość nie może być zmieniona):

#include <vector> 
#include <type_traits> 

int main() 
{ 
    // A non-const vector... 
    std::vector<int> v = { 1, 2, 3, 4, 5 }; 

    auto i = v.begin(); 
    static_assert(
     std::is_same<decltype(i), decltype(v)::iterator>::value, 
     //          ^^^^^^^^ 
     //          ...non-const iterator! 
     "What?"); 

    // A const vector... 
    std::vector<int> const vc = { 1, 2, 3, 4, 5 }; 
    auto ic = vc.begin(); 
    static_assert(
     std::is_same<decltype(ic), decltype(vc)::const_iterator>::value, 
     //          ^^^^^^^^^^^^^^ 
     //          ...const iterator! 
     "What?"); 
} 

Listy inicjalizujące są z definicji kolekcjami niezmiennymi. Na § 18,9/2 C++ 11 Standard:

obiektu typu initializer_list<E> zapewnia dostęp do tablicy obiektów typu const E. [...]

Ponieważ list initializer są zbiory const elementów, gdy cbegin() i cend() funkcje faktycznie robić dokładnie to samo, że begin() i end() zrobić.

W rzeczywistości iterator i const_iterator są zarówno zdefiniowane jako wskaźniki do stałych elementów listy initializer typ wartości, więc spierać czy jest to przypadek, że begin() i end() zawsze powrócić const_iterator (jak zakładam), czy też zawsze return iterator.

To jest jak Paragraf 18.9/1 o C++ 11 standard definiuje szablon initializer_list Klasa:

namespace std { 
    template<class E> class initializer_list { 
    public: 
     typedef E value_type; 
     // ... 
     typedef const E* iterator; 
     typedef const E* const_iterator; 
     // ... 
     constexpr const E* begin() const noexcept; // first element 
     constexpr const E* end() const noexcept; // one past the last element 
    }; 

    // ... 
} 
+6

Pamiętam, kiedy przyzwyczaiłem się do otrzymania repa na SO, ale wtedy pojawiła się osoba, która odpowiedziała na wszystkie dobre pytania w C++ w doskonałej formie . Teraz mogę tylko głosować. +1 – GManNickG

+0

@GManNickG: Jestem pochlebiony i chociaż wierzę, że komplementujesz mnie bardziej, niż na to zasługuję, bardzo się cieszę, że otrzymałem twoje wsparcie. Dziękuję Ci. –

+2

@GManNickG: Pomyśl o wszystkich ludziach z C#, którzy byli Jonami od pierwszego dnia. – MSalters

Powiązane problemy