std::array C++11
-
Nein, nein. Der Kommentar heißt hier einfach, dass der Name des Arrays nur als Beispiel gegeben ist, und kein tatsächlicher Member von
array
ist.
-
17.5.2.3 lesen und verstehen
-
camper schrieb:
17.5.2.3 lesen und verstehen
Es kann praktisch nur ein echtes Array als Member geben. Der Standard fordert eine Initialisierungssyntax (s. §23.3.2.1/2), die nur ein Array als Member ermöglicht. Ein
vector
fällt durch, weil brace-elision nur für Aggregate funktioniert.Die einzige andere Möglichkeit besteht darin, das Subaggregat so zu definieren, dass es genauso viele Member hat wie das Template-Argument vorgibt. Das ist nur leider impraktikabel, da so nur eine maximale Größe von 4096 möglich wäre - siehe Anhang B.
-
also mir fällt da so ein
template <typename T, size_t N> struct array { ... T elems[1][1][1][1][1][N][1][1][1][1]; };
oder
template <typename T, std::size_t N> struct array { array<T,(N+1)/2> x; array<T,N/2> y; }; template <typename T> struct array<T,1> { T x; }; template <typename T> struct array<T,0> { };
-
Eines Tages erwisch' ich dich, du mieser Hund!
-
Warte! Letzteres ist gar nicht Standardkonform, weil...
Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other
Und
The elements of an
array
are stored contiguously, meaning that ifa
is anarray<T, N>
then it obeys the identity&a[n] == &a[0] + n
for all0 <= n < N
.
-
Skym0sh0 schrieb:
Wäre es dann nicht angebracht, dass array selbst entscheidet, wann ein Array auf dem Stack oder dem Heap liegen soll?!
Das wäre fein, sagen wir mal ab 65k geht's auf den Heap.
Könnte gcc Compilererweiterungen einbasteln, und in der gcc-stdlib benutzen, damit das klappt und dem Standard nicht widerspricht?
-
Könnte gcc Compilererweiterungen einbasteln, und in der gcc-stdlib benutzen, damit das klappt und dem Standard nicht widerspricht?
Warum nicht einfach selber was basteln? Mit partieller Spezialisierung ist das ein Klacks. Muss doch nicht in den Standard,
dynarray
hats auch nicht geschafft.Und ich will mal sehen, wie man da um den Standard herum kommt, gerade wegen der Speicherkontinuitätsregel und der Initialisierungssyntax. Ich wette, jetzt gehen auch camper die Ideen aus.
-
Hier, so ähnlich:
#include <vector> #include <memory> template< typename T, std::size_t N, typename=void > struct Array { T _elems[N]; // evt. mit Trick um zero-size-arrays zu erlauben // ... }; 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] }; // .. }; int main() { Array<int, 70000> a; }
So ist es sogar immer noch ein Aggregat.
-
Arcoth schrieb:
Könnte gcc Compilererweiterungen einbasteln, und in der gcc-stdlib benutzen, damit das klappt und dem Standard nicht widerspricht?
Warum nicht einfach selber was basteln? Mit partieller Spezialisierung ist das ein Klacks. Muss doch nicht in den Standard,
dynarray
hats auch nicht geschafft.Jo, was lokales dazu habe ich schon seit 10 Jahren, naja so ähnlich, den Vector<type,size,onHeap=(size>=8192)> oder so. Array brauche ich eher nie, weil irgendwie die Daten dann doch angekrochen oder gestreamt oder berechnet mit ungewisser Ergebnisanzahl oder so kommen.
Wenn ich man drüber nachdenke, würde wohl auch >=64 fast reichen, denn wenn man die 64 Elemente tatsächlich anfassen will, kostet gegen die Berechnungen im Vector/Array das Allokieren/Deallokieren gar nicht mehr als einen Takt pro Element. Pah, 64-Bitter packen 8192 kompromisslos. Hast mich wieder zu nutzlosem Nachdenken gebracht, Du Schalk.
-
Ich - bin - kein - Schalk! Du bist der Schalk!
-
Arcoth schrieb:
Ich - bin - kein - Schalk! Du bist der Schalk!
Wird noch, ich setze weiterhin große Hoffnungen in Dich.
-
Arcoth schrieb:
Warte! Letzteres ist gar nicht Standardkonform, weil...
Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other
genau: might
Nirgendwo wird verlangt, dass die Implementation der Standardbibliothek portabel sein muss.Arcoth schrieb:
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] }; // .. };
So ist es sogar immer noch ein Aggregat.
Ich glaube nicht. Initialisierer für nicht-statischen Member und so...
-
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).
-
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?
-
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...
-
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.
-
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?
-
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
-
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.