arrays überladen
-
Funktioniert mit Clang 3.0:
#include <array> template <class First, class ...Rest> auto make_array(First && first, Rest && ...rest) -> std::array<First, 1 + sizeof...(Rest)> { return { std::forward<First>(first), std::forward<Rest>(rest)... }; } int main() { const auto a = make_array(1, 2, 3, 4); static_assert(std::is_same<const std::array<int, 4>, decltype(a)>::value, "make_array liefert einen unerwarteten Typ"); }Ist das korrekt und optimal so?
-
Shade Of Mine schrieb:
Ethon schrieb:
Da sowohl normale Arrays als auch std::array eine konstante Größe erfordern, ist es total egal wie gut man im Code die Größe bestimmen kann, da sie sowieso bekannt sein muss.
Das ist aber leider nicht gegeben. Sobald ich das Array naemlich an eine Funktion uebergebe verliere ich idR diese Information. Ich kann natuerlich immer aufpassen die korrekte Groesse immer mitzugeben - aber bei std::array ist sie immer da egal was passiert.
std::array ist in jeder einzelnen Situation besser (bzw. gleich gut) als ein plain array. Jeder einzelnen.
Nö, bei std::array musst du die Information doch auch explizit mitgeben.
template<std::size_t Size> void i_like_ints(std::array<int, Size>& ints) {}
-
Ethon schrieb:
Nö, bei std::array musst du die Information doch auch explizit mitgeben.
Bei einem plain array musst du das nicht.

-
Ethon schrieb:
template<std::size_t Size> void i_like_ints(std::array<int, Size>& ints) {}Keine Ahnung warum man so ein template haben will, aber bitte - funktioniert einwandfrei:
auto a=make_array(1,2,3,4,5); i_like_ints(a);
-
Shade Of Mine schrieb:
aber folgendes nicht?
template <typename Head, typename... Tail> std::array<Head,1+sizeof...(Tail)> make_array(Head head, Tail const&... tail) { return std::array<Head,1+sizeof...(Tail)> ({ head, tail... }); }Weil hierfür ein list-Konstruktor erforderlich wäre.
-
Mein Vorschlag
template <typename... Args> constexpr std::array<typename std::common_type<typename std::decay<Args>::type...>::type, sizeof...(Args)> make_array(Args&&... args) { return { std::forward<Args>( args )... }; }evtl. noch eine Prüfung, dass kein narrowing stattfindet.
-
camper schrieb:
Weil hierfür ein list-Konstruktor erforderlich wäre.
Gibt es einen Grund warum es so einen ctor nicht gibt?
Klar kann man nicht statisch ueberpruefen dass die elementanzahl passt - aber das waere per assert ja auch ok...
-
Shade Of Mine schrieb:
Gibt es einen Grund warum es so einen ctor nicht gibt?
Weil array ein Aggregat sein soll. Wenn es keins wäre und ein List-Konstruktor existierte, hätte man u.a. auch das Problem, dass Narrowing verboten wäre; da array nichts Neues ist, hätte man dann auch mit zusätzlichen Inkompatibilitäten gegenüber C++03 zu kämpfen.
-
camper schrieb:
Shade Of Mine schrieb:
Gibt es einen Grund warum es so einen ctor nicht gibt?
Weil array ein Aggregat sein soll.
oh, ok.
macht natuerlich sinn.
-
Shade Of Mine schrieb:
camper schrieb:
Shade Of Mine schrieb:
Gibt es einen Grund warum es so einen ctor nicht gibt?
Weil array ein Aggregat sein soll.
oh, ok.
macht natuerlich sinn.Wenn man weiter denkt, eigentlich nicht.
array ist ja deshalb als Aggregat eingeführt worden, damit diese Art Initialisierung (auch in C++03) durchgeführt werden kann. Jetzt wäre das an sich nicht mehr erforderlich. Und weil es unterspezifiziert ist, kann man std::array nicht felxibel einsetzen, wenn man portabel bleiben will: es wird nämlich nicht gesagt, wie die vollständige Klammerung auszusehen hat, sondern nur, dassarray<T, N> a = { initializer-list };funktionieren soll. Dabei findet allerdings mit Sicherheit brace-elision statt, und gerade die ist ja in anderen Kontexten (z.B. Member-Initialisierer) nicht zulässig.
Nur steht eben nirgendwo, dassarray<T, N> a = {{ initializer-list }};a) möglich und b) die vollstäng geklammerte Variante ist.
Beispielsweise könnte array ja so aussehen
template <typename T, size_t N> struct array { ... T elems[1][1][1][N]; };unsinnig, aber möglich.