2017-01-27 19 views
3

ich den Code aus Header-Datei initializer_list und umbenannt den Klassennamendie UMSETZUNG von std :: initializer_list

template<class _E> 
    class my_initializer_list 
    { 
    public: 
     typedef _E  value_type; 
     typedef const _E&  reference; 
     typedef const _E&  const_reference; 
     typedef size_t  size_type; 
     typedef const _E*  iterator; 
     typedef const _E*  const_iterator; 

    private: 
     iterator   _M_array; 
     size_type   _M_len; 

     // The compiler can call a private constructor. 
     constexpr my_initializer_list(const_iterator __a, size_type __l) 
     : _M_array(__a), _M_len(__l) { } 

    public: 
     constexpr my_initializer_list() noexcept 
     : _M_array(0), _M_len(0) { } 

     // Number of elements. 
     constexpr size_type 
     size() const noexcept { return _M_len; } 

     // First element. 
     constexpr const_iterator 
     begin() const noexcept { return _M_array; } 

     // One past the last element. 
     constexpr const_iterator 
     end() const noexcept { return begin() + size(); } 
    }; 

und den Code my_initializer_list kopiert:

int main() 
{ 
    my_initializer_list<int> foo = {1,2,3}; 

    return 0; 
} 

und erhalten den Fehler:

could not convert '{1, 2, 3}' from '<brace-enclosed initializer list>' to 'my_initializer_list<int>' 

Meine Frage: Wie STL die initializer_list Klasse implementieren?

+0

Aus demselben Grund können Sie die Definition von 'std :: typeinfo' nicht copy-paste und verwenden Sie dann' typeid' eins zu bekommen. – immibis

Antwort

5

Es mit std::initializer_list funktioniert, weil, obwohl std::initializer_list eine Klasse ist, ist es nicht eine regelmäßige Klasse. Es ist eine sehr, sehr spezielle Klasse, in dem Sinne, dass, wenn Sie auto x = {1,2,3}; schreiben, der Compiler zu folgx zu std::initializer_list<int> gehen und es entsprechend initialisieren wird. Der Compiler macht schwarze Magie hier, um die Typ-Inferenz und Initialisierung durchzuführen. Es ist nicht nur Bibliothek-Funktion. Es ist auch eine Core-Language-Funktion.

Wenn Sie stattdessen my_initializer_list verwenden, muss der Konstruktor std::initializer_list akzeptieren, damit der Compiler die schwarze Magie für Sie ausführen kann.

Beachten Sie, dass {1,2,3} eine Art lose Ausdruck ist — gut, zu pedantisch zu sein, ist es nicht einmal ein Ausdruck; Nur in einigen speziellen Fällen kann es verwendet werden, um Objekte mithilfe einiger spezieller Regeln zu initialisieren. Zum Beispiel sehen:

auto items = {1,2,3}; //OK: items is inferred to be std::initializer_list<int> 
         //must #include <initializer_list> 

jedoch bei Vorlagen, die Regel ist anders:

template<typename T> 
void f(T const & items); 

f({1,2,3}); //ILL-FORMED: T cannot be deduced to be 
      //std::initializer_list<int> or anything else 
      //even if you use #include <initializer_list> 

f(std::initializer_list<int>{1,2,3}); //OK: #include <initializer_list> 

f(std::vector<int>{1,2,3}); //OK: #include <vector> 
          //because std::vector accepts std::initializer_list<T> 

Hoffnung, das hilft.

Verwandte Themen