Ich versuche, eine statische und konstante Array mit dem kumulativen Produkt eines Template-Parameter Pack zu initialisieren:Kumulative Produkt von Template-Parameter-Pack
template <int ...D>
class Foo
{
static const std::array<const Size, sizeof...(D)> _array;
};
template <int...D> const std::array<const int, sizeof...(D)> Foo<D...>::_array =
{ cumulative_product<D...>() };
Wie kann ich die Funktion cumulative_product <>() schreiben, wie dass es D ... in das kumulative Produkt von D umwandelt? Z.B.
Foo<1,2,3,4>::_array;// = {1,1*2,1*2*3,1*2*3*4} = {1,2,6,24}.
Lösung: Massives Sie danken für Ihre ausgezeichnete C++ 14-Lösung @bogdan und Verbesserungen in meine C++ 11-Lösung.
#include <array>
#include <iostream>
#define CPP_VERSION 11
#if CPP_VERSION >= 14
// Credit: @bogdan at http://stackoverflow.com/q/37373602/6367128
template<int... Args> constexpr std::array<int, sizeof...(Args)> cumulative_product(int seed = 1) { return{ { seed *= Args ... } }; }
#elif CPP_VERSION == 11
// Acknowledgement: Huge thank you to @bogdan for making the code more portable, concise and readable!
namespace details
{
template<int N, int i, int j, int ...Args> struct c_product_gen // N counts down to zero
{
static constexpr std::array<int, sizeof...(Args)+1> get() { return c_product_gen<N - 1, i*j, Args..., i*j>::get(); }
};
template<int i, int j, int ...Args> struct c_product_gen<0, i, j, Args...> // The end point of the template recursion
{
static constexpr std::array<int, sizeof...(Args)+1> get() { return { { j, Args... } }; }
};
}
template<int... Args> constexpr std::array<int, sizeof...(Args)> cumulative_product() { return details::c_product_gen<sizeof...(Args), 1, Args...>::get(); }
#else // CPP_VERSION < 11
template<int... Args> constexpr std::array<int, sizeof...(Args)> cumulative_product()
{
static_assert(false, "C++ version 11 or greater is required.");
return std::array<int, sizeof...(Args)>();
}
#endif
int main()
{
constexpr auto a = cumulative_product<1,2,3,4,5>();
for(auto i : a) std::cout << i << ' '; // Output: 1 2 6 24 120
std::cout << '\n';
}
können Sie mit C++ 14? –
@PiotrSkotnicki Ja, absolut. – Judge
Ich mag die Rotation der Argumente, nette! Beachten Sie, dass sich Clang und GCC im pedantischen Modus über einige Template-Techniken beschweren, die es wert sind, für maximale Portabilität und Standardkonformität festgelegt zu werden. Insbesondere fangen GCC und EDG eine wichtige ein, die Clang und MSVC ignorieren - die teilweise Spezialisierung von "c_product_gen" muss spezialisierter als die primäre Vorlage sein. Übrigens macht das Reparieren "remove_first" überflüssig. [Hier ist eine Version] (http://melpon.org/wandbox/permlink/hHfoKAlqwayCWmSt) mit allen Anpassungen. – bogdan