std::array C++11


  • Mod

    Ich glaube nicht. Initialisierer für nicht-statischen Member und so...

    An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).


  • Mod

    Arcoth schrieb:

    Ich glaube nicht. Initialisierer für nicht-statischen Member und so...

    An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

    Quelle?


  • Mod

    N3797 natürlich. :p

    Übrigens:

    If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute that program.

    Edit: Das Zitat ist völlig Sinnlos, weil - sobald die Standardbibliothek nicht mehr standardkonform ist - natürlich auch das Programm nicht standardkonform ist...


  • Mod

    Arcoth schrieb:

    N3797 natürlich. :p

    (Noch) kein Standard also. Das sollte nicht unterschlagen werden. Diese spezielle Änderung geht auf N3653 zurück.

    Für sinnvoll halte ich die Spezialisierung

    template< typename T, std::size_t N >
    struct Array<T, N, typename std::enable_if<N >= (1 << 16)>::type>
    {
        std::unique_ptr<T[]> _elems{ new T[N] };
    
        // ..
    };
    

    trotzdem nicht. Da die Aggregatinitialisierung nicht so funktioniert, wie sie soll, ist es unbedeutend, dass es in C++14 nun überhaupt ein Aggregat ist.

    Array<int, 100000> x = { 0, 1, 2 }; // geht nicht
    

    Der unique_ptr sollte sicher eher ein clone_ptr sein, sonst haben wir auch keine Kopiersemantik.
    std::array ist nur deshalb ein Aggregat, weil vor initializer_list und variadic templates eingeführt wurde. Eine modernisierte Variante würde statt dessen auf einen geeigneten Konstruktor setzen.

    Arcoth schrieb:

    Übrigens:

    If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute that program.

    Edit: Das Zitat ist völlig Sinnlos, weil - sobald die Standardbibliothek nicht mehr standardkonform ist - natürlich auch das Programm nicht standardkonform ist...

    Das ist nur eine sinnlose Interpretation. Der Begriff "program" schließt hier die Implementation natürlich nicht mit ein.
    Und ob eine Implementation den Standard 100% richtig umsetzt oder nicht spielt keine Rolle in Hinblick auf die Konformität eines Programmes, dass diese nutzt.


  • Mod

    Noch) kein Standard also.

    Egal. Die Änderung wird bleiben, weil sie sinnvoll ist.

    Da die Aggregatinitialisierung nicht so funktioniert, wie sie soll, ist es unbedeutend, dass es in C++14 nun überhaupt ein Aggregat ist.

    Die Variante bekommt natürlich noch einen initializer-list-Konstruktor, und ist damit sowieso kein Aggregat mehr. Wollte es nur anmerken, weil ich genau die entfernte Regel gut fand.

    Der unique_ptr sollte sicher eher ein clone_ptr sein, sonst haben wir auch keine Kopiersemantik.

    Das gibt es im Standard gar nicht.

    Und ob eine Implementation den Standard 100% richtig umsetzt oder nicht spielt keine Rolle in Hinblick auf die Konformität eines Programmes, dass diese nutzt.

    Wenn ich ein Programm schreibe, dass (&arr[0])[5] benutzt, ist das natürlich UB.

    Du willst mir also weismachen, dass die Standardbibliothek auch einfach falsch implementiert werden kann, und das dem Standard völlig egal ist?


  • Mod

    Arcoth schrieb:

    Der unique_ptr sollte sicher eher ein clone_ptr sein, sonst haben wir auch keine Kopiersemantik.

    Das gibt es im Standard gar nicht.

    Dann wirst du einen bauen müssen.

    Arcoth schrieb:

    Du willst mir also weismachen, dass die Standardbibliothek auch einfach falsch implementiert werden kann, und das dem Standard völlig egal ist?

    Präzisier mal deine Frage. Dem Standard ist egal wie eine Sprachimplementation funktioniert. siehe auch 1.4/2


  • Mod

    Ich bin dabei aber auf ein Problem gestoßen. Da clone_ptr die Größe ja eigentlich nicht speichern sollte, kann er auch das Array nicht kopieren.


  • Mod

    Arcoth schrieb:

    Ich bin dabei aber auf ein Problem gestoßen. Da clone_ptr die Größe ja eigentlich nicht speichern sollte, kann er auch das Array nicht kopieren.

    Was hindert dich daran, clone_ptr<T[N]> zu verwenden?


  • Mod

    Ich update gerade zu GCC 4.9, weil ich hoffe, dass so auch die Standardbibliothek geupdated wird, und ich so add_rvalue_reference_t verwenden kann.

    Edit: Weg mit dem Code, der ist voller Bugs. Man, ich muss das viel strenger Testen.


  • Mod

    Die Variante, die ich ausprobiert habe, war folgende: clone_ptr leitet von unique_ptr ab und stellt entsprechende Kopier(und ggf. zu Überladungszwecken Move-)Semantik bereit.

    Das klappt nur irgendwie nicht, denn im Kopierkonstruktor von clone_ptr sollten ja auch alle Kopierkonstruktoren der Arrayelemente aufgerufen werden - nur wie ist das möglich? Nur äußerst umständlich...

    template< typename, std::size_t, std::size_t inits, typename = typename make_index_list<inits>::type >
    struct Copier;
    
    template< typename T, std::size_t N, std::size_t inits, std::size_t ... Indices >
    struct Copier<T, N, inits, index_list<Indices...>>
    {
    	static T* copy( T const* from )
    	{
    		return new T[N]{ from[Indices]... };
    	}
    };
    

    Ist so eine Möglichkeit.

    Ist deutlich kniffliger als ich dachte.


  • Mod

    Arcoth schrieb:

    Ist deutlich kniffliger als ich dachte.

    Nur, weil du auf new T[N] bestehst.


  • Mod

    Einen Wrapper-Typen für das Array?


  • Mod

    Ich habe das schon mal ausprobiert, jetzt erinnere ich mich wieder was daran nicht ging: Wenn ich den Konstruktor von unique_ptr erbe... der Rest ist klar.

    Das heißt, ich müsste lediglich die Zeiger-Konstruktoren selber schreiben. Tjoa.


Anmelden zum Antworten