2016-05-10 94 views
1

假設我想聲明一個本地靜態常量數組,但我不知道它在編譯時的初始化值,必須首先計算它們。 例如,我有一個陣列int p[100]。我寫了一個循環來填充前100個素數。在這些計算之後,我定義了一個static const int primes[100],它必須由p的值初始化。我怎樣才能做到這一點?使用另一個數組的值初始化本地靜態常量數組

P.S. 「爲什麼我想聲明一個本地靜態const對象?可能沒有一個滿意的答案,但我認爲這不是這種情況。

P.S.S.我只是提到素數就是一個例子。這不是重點。

P.S.S.S.比方說p有1000000個成員。那麼user2079303建議的解決方案肯定值得讚賞。

+1

@EddeAlmeida - 那根本不是真的。常量可以在運行時初始化,只是沒有改變。考慮函數本地的常量 – Smeeheey

+0

好@Smeeheey。我刪除了我之前做出的愚蠢評論。 –

+0

那麼我應該說,常量在創建時被初始化,並且在那一刻之後不能被改變。因此,人們不能僅僅創造一個常量,以便稍後給它一個價值。它是否正確? –

回答

2

這是可能的初始化在運行時靜態常量數組,但有點乏味:

int* init = get_run_time_array(); 
static const int primes[100] { 
     init[0], init[1], init[1], init[2], init[3], init[4], init[5], // ... 
}; 
1

迴避你的問題,它實際上是完全可行的有你的素數在編譯時使用模板的元計算節目。以下代碼顯示了執行此操作的可能方法。主函數創建實例化PrimeGen類型以生成前100個素數的編譯時std ::數組。道歉,代碼有點難以閱讀,因爲這裏有很多模板樣板。基本上大部分邏輯發生在第一PrimeGen專業化,它使用埃拉託塞尼的篩以生成素數,使用以下基本公式:

  1. 開始與N = 100(所需數量尚未生成),接着= 2,一個空素數列表和一個空過濾器列表

  2. 檢查Next是否爲素數(即,傳遞所有現有的過濾器)。如果是這樣,將它添加到素數列表中,遞減N並添加一個新的過濾器,它將無法傳遞可被Next整除的任何數字。

  3. 遞歸具有上述修改的參數PrimeGen的下一個專業化以及與接下來遞增到下一個+ 1
  4. 終止時N = 0

顯然這程序的編譯時間會相對較長因爲編譯器會計算素數。

#include <iostream> 
    #include <array> 

    template <size_t Mod> 
    struct ModFilter 
    { 
     template<size_t N> 
     static constexpr bool apply() 
     { 
      return N % Mod != 0; 
     } 
    }; 

    template <size_t N, typename ... Filters> 
    struct CheckFilters; 

    template <size_t N> 
    struct CheckFilters<N> 
    { 
     static const bool pass = true; 
    }; 

    template <size_t N, typename Filter, typename ... Filters> 
    struct CheckFilters<N, Filter, Filters...> 
    { 
     static const bool pass = Filter::template apply<N>() && CheckFilters<N, Filters...>::pass; 
    }; 

    template<typename ... Filters> 
    struct FilterPack{}; 

    template<size_t ... Numbers> 
    struct NumberList{}; 

    template <size_t N, bool doAppend, typename Numbers> 
    struct ConditionalAppend 
    { 
     typedef Numbers Output; 
    }; 

    template <size_t N, size_t ... Numbers> 
    struct ConditionalAppend<N, true, NumberList<Numbers...>> 
    { 
     typedef NumberList<Numbers..., N> Output; 
    }; 

    template <size_t N, bool doAppend, typename Filters> 
    struct ConditionalAppendFilter 
    { 
     typedef Filters Output; 
    }; 

    template <size_t N, typename ... Filters> 
    struct ConditionalAppendFilter<N, true, FilterPack<Filters...>> 
    { 
     typedef FilterPack<Filters..., ModFilter<N>> Output; 
    }; 

    template<size_t N, size_t Next, typename Numbers, typename Filters> 
    struct PrimeGen; 

    template<size_t N, size_t Next, size_t ... Numbers, typename ... Filters> 
    struct PrimeGen<N, Next, NumberList<Numbers...>, FilterPack<Filters...>> 
    { 
     static constexpr std::array<size_t, N + sizeof...(Numbers)> numbers 
      = PrimeGen<CheckFilters<Next, Filters...>::pass ? N-1 : N, 
         Next+1, 
         typename ConditionalAppend<Next, CheckFilters<Next, Filters...>::pass, NumberList<Numbers...>>::Output, 
         typename ConditionalAppendFilter<Next, CheckFilters<Next, Filters...>::pass, FilterPack<Filters...>>::Output> 
       ::numbers; 

     static const int size = N + sizeof...(Numbers); 
    }; 

    template<size_t Next, size_t ... Numbers, typename ... Filters> 
    struct PrimeGen<0, Next, NumberList<Numbers...>, FilterPack<Filters...>> 
    { 
     static constexpr std::array<size_t, sizeof...(Numbers)> numbers = {Numbers...}; 
     static const int size = sizeof...(Numbers); 
    }; 

    template<size_t N, size_t Next, size_t ... Numbers, typename ... Filters> 
    constexpr std::array<size_t,N + sizeof...(Numbers)> PrimeGen<N, Next, NumberList<Numbers...>, FilterPack<Filters...>>::numbers; 

    template<size_t Next, size_t ... Numbers, typename ... Filters> 
    constexpr std::array<size_t,sizeof...(Numbers)> PrimeGen<0,Next,NumberList<Numbers...>,FilterPack<Filters...>>::numbers; 

    int main() 
    { 
     using MyGen = PrimeGen<100, 2, NumberList<>, FilterPack<> >; 

     for(int i=0; i<MyGen::size; ++i) 
      std::cout << MyGen::numbers[i] << std::endl; 

     return 0; 
    } 
+0

雖然我以最好爲例,但這不是重點,但是您的解決方案似乎有點合法。 +1 –

0

最有效的解決方案將是:

static const int primes[100] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541 }; 

你甚至可以用你的整個p計算做掉了。

+1

你在開玩笑吧。對? –

+0

沒有。當結果已知時,爲什麼要浪費時間進行計算? –

0

我剛剛讀了this great answer到SO中的另一個問題,並計算出來。沒有必要聲明局部變量爲static const。似乎只有static才足以使計算值保持在範圍之外。

+0

這聽起來不對。 –

+0

爲什麼? @LightnessRacesinOrbit –

+0

這裏沒有足夠的細節可以說,但是從你告訴我們的很少,這聽起來像是一種誤解。 –