2015-12-01 20 views
10

Ich möchte ein zu einem anderen std::array konvertieren, jedes seiner Elemente mit einer bestimmten Zahl multipliziert.Multiplizieren jedes Element eines std :: -Array zur Kompilierungszeit

Was ich jetzt offensichtlich nicht funktioniert:

#include <array> 
#include <iostream> 
#include <utility> 

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
            std::index_sequence<Is...>) { 
    return std::array<T, N>{{src[Is]...}}; // How can I multiply each of src's elements? 
} 

int main(int argc, char *argv[]) { 
    constexpr std::array<int, 3> arr = {1, 2, 3}; 
    constexpr auto t = multiply(arr, std::make_index_sequence<3>{}); 
    for (auto &el : t) std::cout << el << std::endl; 
    return 0; 
} 

Meine Frage ist: Wie kann ich über jedes Element bei der Kompilierung durchlaufen oder wie kann ich die gleiche Funktion (in meinem Fall gelten: mehrfach um 2) zur Kompilierzeit?

Antwort

14

Sie können es in der folgenden Art und Weise tun:

template<typename T> 
constexpr T mult(T const &a, T const &b) { return a * b; } 

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
            std::index_sequence<Is...>) { 
    return std::array<T, N>{{mult(src[Is], src[Is])...}}; 
} 

Live Demo

Oder wenn Sie durch eine Zahl multiplizieren möchten, können Sie ändern:

template<typename T> 
constexpr T mult(T const &a, T const &b) { return a * b; } 

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, 
            std::index_sequence<Is...>, T const &mul) { 
    return std::array<T, N>{{mult(src[Is], mul)...}}; 
} 

Live Demo

Wie in cppreference erläutert:

Ein Muster gefolgt von einer Ellipse, in der der Name mindestens eines Parameter-Packs mindestens einmal vorkommt, wird auf null oder mehr durch Kommas getrennte Instanziierungen des Musters erweitert, wobei der Name des Parameter-Packs durch ersetzt wird jeder der Typen aus der Packung, um. Pack-Erweiterungen können nur in Pack-Erweiterungskontexten auftreten. Diese sind im Wesentlichen:

  • verspannt Initialisierung
  • initializer Listen
  • Aggregat Initialisierungen
  • Funktion ruft
  • Array Initialisierungen

Edit:

als T.C. in den Kommentaren darauf können Sie es auch so einfach wie:

template <class T, size_t... Is, size_t N> 
constexpr std::array<T, N> multiply(std::array<T, N> const &src, std::index_sequence<Is...>, T const &mul) { 
    return std::array<T, N>{{(src[Is] * mul)...}}; 
} 

Live Demo

+0

Wie funktioniert das '{{mult (src [Is], src [Ist]) ...}' Teil der Arbeit genau ? Das "..." ist in diesem Fall etwas verwirrend. – syntagma

+0

@REACHUS Dies ist eine der Möglichkeiten, Packs zu erweitern. Warte ich versuche es zu erklären. – 101010

+0

Danke, noch eine Frage: Gibt es eine Möglichkeit, 'mult' durch ein Lambda zu ersetzen? Ich habe es versucht, aber es sieht so aus, als ob es nicht möglich sein wird, da lambdas nicht "constexpr's" sein können. – syntagma