Eigene Impl der std::initializer_list funktioniert nicht
-
Hi, ich habe eine eigene Container Klasse programmiert, die ich nun mit einer "initializer_list" versehen wollte. Z.B. so:
template <class T> MyContainer<T>::MyContainer(std::initializer_list<T> initializer) : _items(new T[(int)initializer.size()]), _size((int)initializer.size()) { std::copy(initializer.begin(), initializer.end(), _items); }Das funktioniert auch wie erwartet (GCC/Linux).
Allerdings möchte ich die Standard Lib nicht verwenden und habe mir die Implementierung des GCC kopiert und den namespace von std in test umbenannt (siehe unten):template <class T> MyContainer<T>::MyContainer(test::initializer_list<T> initializer) : _items(new T[(int)initializer.size()]), _size((int)initializer.size()) { std::copy(initializer.begin(), initializer.end(), _items); }Blöderweise funktioniert das ganze nun nicht mehr. Wer kann mir erklären warum?
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.4/a01223.htmlDie Implementierung von Apple funktioniert wenn ich diese kopiere leider auch nicht.
https://opensource.apple.com/source/libcpp/libcpp-31/include/initializer_listnamespace test { template<class _E> class 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; constexpr initializer_list(const_iterator __a, size_type __l) : _M_array(__a), _M_len(__l) { } public: constexpr initializer_list() : _M_array(0), _M_len(0) { } constexpr size_type size() { return _M_len; } constexpr const_iterator begin() { return _M_array; } constexpr const_iterator end() { return begin() + size(); } }; template<class _Tp> constexpr const _Tp* begin(initializer_list<_Tp> __ils) { return __ils.begin(); } template<class _Tp> constexpr const _Tp* end(initializer_list<_Tp> __ils) { return __ils.end(); } }
-
Fehlermeldung ist übrigens:
error: could not convert ‘{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 42, 100}’ from ‘<brace-enclosed initializer list>’ to ‘MyContainer<int>’
MyContainer<int> container = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 , 14, 15, 42, 100 };Ich habe nur die GCC Implementierung in meinen Code kopiert und den "std" namespace zwecks Eindeutigkeit des Klassennamens in "test" umbenannt. Mit der originalen "std::initializer_list" gehts.
-
Wie wird aus {...} eine test::initializer_list?
-
Keine Ahnung, das ist doch die "Magie" dieses neuen initializer_list Features von C++14. Meine Vermutung war, dass der Compiler anhand der führenden doppelten Unterstriche erkennt, dass es für ihn reservierte Variablen sind und den Konstruktor der sogar privat ist dann aufruft und die größe des dynamischen Arrays an den size_t Parameter übergibt. Das war ja das Problem, dass man nachträglich die größe eines dynamischen Arrays nicht mehr feststellen konnte. Ansonsten könnte man sich diese Klasse ja auch sparen.
// The compiler can call a private constructor. constexpr initializer_list(const_iterator __a, size_type __l) : _M_array(__a), _M_len(__l) { }
-
Übrigens hier mal ein Testprogramm:
-
Oh man, das darf doch nicht wahr sein. Ich hatte schon vermutet dass diese initializer_list eine absolute frickel scheiße ist. Und wie es aussieht ist das wirklich so:
https://stackoverflow.com/questions/247538/which-standard-c-classes-cannot-be-reimplemented-in-c
Anstatt ein wiederverwendbares Feature hinzuzufügen, scheint dies and die initializer_list gekoppelt zu sein. Sprich man muss immer diese Klasse benutzen und kann dies agr nicht in einer eigenen implementierung nachbilden. Sitzen in diesem C++ Gremium eigentlich nur noch grauhaarige Vollidition... Mann mannn mann