3

私はテンプレートパラメータパックの累積積を持つ静的および定数配列初期化しようとしている:私は、関数cumulative_productを書くにはどうすればよい累積製品パック

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...>() }; 

を<>()、などD ...の累積積にD ...を変換するということですか?例えば。

Foo<1,2,3,4>::_array;// = {1,1*2,1*2*3,1*2*3*4} = {1,2,6,24}. 

ソリューション:大規模なあなたの優れたC++ 14解決策、そして私のC++ 11溶液への改善のために@bogdanをお願い致します。

#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'; 
} 
+0

あなたはC++ 14を使用することができますか? –

+0

@PiotrSkotnickiはい、絶対に。 – Judge

+1

私は引数の回転、好きなものが好きです!ペタンティックモードのClangとGCCは、移植性と標準適合性を最大限にするための修正が必要なテンプレートに関するいくつかのテクニカルについて不満を持ちます。特に、GCCとEDGは、ClangとMSVCが無視する重要な要素を正しくキャッチしています。つまり、 'c_product_gen'の部分的な特殊化はプライマリテンプレートよりも特殊化する必要があります。ちなみに、 'remove_first'を不要にする固定化。すべての調整をした[ここにバージョンがある](http://melpon.org/wandbox/permlink/hHfoKAlqwayCWmSt) – bogdan

答えて

3
#include <array> 
#include <utility> 
#include <cstddef> 

template <int... D, std::size_t... Is> 
constexpr std::array<int, sizeof...(D)> cumulative_product(std::index_sequence<Is...>) 
{ 
    static_assert(sizeof...(D), "Missing initializers"); 
    int a[]{ D... }; 
    for (int i = 1; i < int(sizeof...(D)); ++i) 
    { 
     a[i] *= a[i-1]; 
    } 
    return {{ a[Is]... }}; 
} 

template <int... D> 
constexpr auto cumulative_product() 
{ 
    return cumulative_product<D...>(std::make_index_sequence<sizeof...(D)>{}); 
} 

template <int... D> 
struct Foo 
{ 
    static constexpr std::array<int, sizeof...(D)> _array = cumulative_product<D...>(); 
}; 

DEMO

+0

素晴らしい答えをありがとう!単に好奇心から、あなたはC++ 11でどうやってそれをすることができますか?それとも不可能なのでしょうか? – Judge

+3

C++ 14の場合、 'テンプレート constexpr std :: array cumulative_product(int seed = 1){return {{seed * = Ds ...} }; } 'で十分です。 @ジャッジ:C++ 11の解決策は間違いありませんが、私はあなたが反復を偽装するのを避けることはできないと思っています。 – bogdan

+0

@bogdan私は、あなたのソリューションは単なる素晴らしいものだと言わざるを得ません。 – Quentin