2015-08-24 8 views
15

Ich habe eine std::array<Foo, 10> und ich möchte eine std::array<Bar, 10> mit einer Funktion von Foo bis Bar erstellen. Normalerweise würde ich std::transform wie so verwenden:Wie erstelle ich ein std :: array mit std :: transform ohne Standardkonstruktor

array<Bar, 10> bars; 
transform(foos.begin(), foos.end(), bars.begin(), [](Foo foo){ 
    return Bar(foo.m_1, foo.m_2); 
}); 

Allerdings ist Bar nicht über einen Standardkonstruktor verfügen, so kann ich das bars Array nicht erstellen. Ich könnte immer vector verwenden, aber es wäre nett, array verwenden zu können, um sicherzustellen, dass ich immer genau 10 Elemente habe. Ist das möglich?

+0

Man könnte so etwas wie eine [nicht ganz noch] (https://www.reddit.com/r/cpp/comments/1njair/stdoptional_and_stddynarray_removed_from_c14_and/) -std [std :: optional] (https verwenden /github.com/akrzemi1/Optional), um den Balken für die Zwecke dieses Arrays zu umbrechen. Zumindest würde das Bar im Allgemeinen nicht zwingen, einen Standardkonstruktor zu haben, und es ist ein nützlicher Bestandteil in einem Projekt (imo). – HostileFork

+1

Wäre ein 'vector.reserve (10)' in Ihrem Code für die Größe '10' nicht ausreichend oder möchten Sie sicherstellen, dass der Client-Code diese Größe nicht ändert? – Niall

+0

In diesem Fall funktioniert 'vector.reserve' gut, aber es ist keine Idee, da diese Sammlung semantisch 10 Elemente haben muss, und das wird nicht in allen Fällen funktionieren. Image, wenn ich es an eine Funktion übergeben muss, die ein 'std :: array & akzeptiert'. – Drew

Antwort

14

Nicht mit std::transform, aber nichts ein wenig Vorlage Magie kann nicht beheben.

template<std::size_t N, std::size_t... Is> 
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos, 
           std::index_sequence<Is...>) { 
    return {{ Bar(foos[Is].m_1, foos[Is].m_2)... }}; 
} 

template<std::size_t N, std::size_t... Is> 
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos) { 
    return foos_to_bars(foos, std::make_index_sequence<N>()); 
} 

std::index_sequence und Freunde sind C++ 14, aber leicht implementierbare in C++ 11. Es gibt wahrscheinlich ein halbes Dutzend Implementierungen für SO allein. /:

+0

Warum die doppelten Klammern in der Return-Anweisung von 'foos_to_bars'? Hat das mit dem Erstellen eines Pack-Erweiterungskontexts zu tun? Wenn ja, ist {{}}} besser als die anderen, die Sie in SO präsentiert haben (zB 'Expander')? –

+1

@NikosAthanasiou Nein, nur die Warnung "fehlende Klammern" des Compilers wird zum Schweigen gebracht. ('std :: array' ist ein Aggregat, das ein eingebautes Array enthält; die äußeren geschweiften Klammern sind für' std :: array'; das innere für das eingebaute. Sie dürfen die inneren geschweiften Klammern verwenden, aber einen Compiler warnt, wenn Sie das tun.) –

Verwandte Themen