2017-03-07 32 views
2

我希望得到一個值數組int buf[]={1...100}。我希望這個數組可以在編譯時使用可變參數模板來構建。這就像Python/Haskell的列表理解等。C++ 14:如何使用可變參數模板創建值的數組1-100

但是C++ 11/14模板能做到嗎? 謝謝

+0

不明白的方式來做到這一點在全局命名空間,但這種陣列可以被聲明爲一個輔助類的靜態成員。不過,如果你的目標只是簡單地初始化一個int數組,那麼只需編寫腳本來機器生成源代碼,而不是混淆模板。如果你的目標是做你的家庭作業,那麼它的全部原因將由你自己弄清楚,而不是讓別人在stackoverflow.com上爲你做家庭作業。 –

回答

4

C++ 14允許在編譯時循環。

constexpr auto make_upto_100() { 
    std::array< int, 100 > ret = {}; 
    for (int i = 0; i != 100; ++ i) ret[i] = i + 1; 
    return ret; 
} 

C++ 11讓像make_index_sequence一個工具,它可能會更喜歡你的想法。 (C++ 14還具有std::[make_]index_sequence。)

template< std::size_t ... i > 
struct index_sequence 
    { typedef index_sequence< i ..., sizeof ... (i) > next; }; 

template< std::size_t last > 
struct index_seq_maker 
    { typedef typename index_seq_maker< last - 1 >::type::next type; }; 

template<> 
struct index_seq_maker<0> 
    { typedef index_sequence<> type; }; 

template< std::size_t n > 
using make_index_sequence = typename index_seq_maker<n>::type; 

template< int ... i > 
constexpr 
std::array< int, 100 > 
make_upto_100(index_sequence< i ... >) 
    { return {{ i + 1 ... }}; } 

constexpr 
std::array< int, 100 > upto_100() = make_upto_100(make_index_sequence<100>{}); 
+0

@RyanHaining固定。 – Potatoswatter

0

嗯,這不是編譯時間,但通常,我希望大多數代碼使用std::iota。在某些情況下,這實際上可能比編譯時魔術更快,因爲編譯時數組需要存儲在可執行文件的.data段中;如果陣列足夠大,則從.data中讀取額外的磁盤頁面可能會比寫入從操作系統中抽取的純內存頁面的速度慢。

簡單的用法是:

int buf[100]; 
std::iota(&buf[0], &buf[100], 1); 

坦率地說,我會從這裏開始,只有開始尋找模板魔法,如果你有運行時初始化一個經過驗證的性能問題。

1

這應該適用於C++ 14。它通過遞歸模板實例工作,將所有值初始化爲constexpr。您應該可以通過更改模板參數來將順序值的大小更改爲所需的任何值。注意非常大的數組可能會遇到遞歸限制:

#include <array> 

template<int NumVal, int ArrSize> 
constexpr void setVal(std::array<int, ArrSize> &constArr) { 
     std::get<NumVal>(constArr) = NumVal + 1; 
     if(NumVal) setVal<NumVal ? NumVal - 1 : 0, ArrSize>(constArr); 
} 

template<int ArrSize> 
constexpr auto arrRange() -> std::array<int, ArrSize> { 
     std::array<int, ArrSize> tmp{}; 
     setVal<ArrSize - 1, ArrSize>(tmp); 
     return tmp; 
} 

constexpr std::array<int, 100> constArr = arrRange<100>(); 

int main() { 
     for(int itr = 0; itr < 100; ++itr) printf("%d ", constArr[itr]); 
} 
3

如果您確實在編譯時進行此設置。你可以用一個integer_sequencestd::array

#include <utility> 
#include <array> 

template <int... Is> // when called below, Is will be 0 - N 
constexpr std::array<int, sizeof...(Is)> make_inc_array_impl(
    std::integer_sequence<int, Is...>) { 
    return {{(Is + 1)...}}; // +1 to start at one instead of [0, 1, ...] 
} 


template <std::size_t N> 
constexpr std::array<int, N> make_inc_array() { 
    return make_inc_array_impl(std::make_integer_sequence<int, N>{}); 
} 

做到這一點,然後用你的尺寸致電

constexpr auto a = make_inc_array<100>(); // [1, 2, ..., 100] 

這遠比一個列表理解不夠靈活,而且你可能方式最好只使用std::iota並在運行時進行初始化。

相關問題