Initialize a local static const array with values of another array
假设我想声明一个局部静态常量数组,但我不知道它的初始值设定项值在编译时,必须首先计算这些值。例如,我有一个数组
另外,"为什么我要声明一个本地静态常量对象?"可能没有令人满意的答案,但我认为情况并非如此。
P.S.S.我提到素数就是一个例子。这不是重点。
P.S.S.S.假设
可以在运行时初始化静态const数组,但有点乏味:
1 2 3 4 | 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], // ... }; |
为了回避您的问题,实际上使用模板元编程在编译时计算素数是完全可行的。下面的代码显示了一种可能的方法。主函数创建实例化primegen类型以生成前100个prime的编译时std::数组。很抱歉,代码有点难阅读,因为这里有很多模板锅炉板。基本上,大多数逻辑发生在第一个素数专业化过程中,该过程使用埃拉托斯滕筛生成素数,使用以下基本公式:
从n=100(尚未生成的必需数字)开始,下一个=2,素数的空列表和过滤器的空列表
检查next是否为prime(即,通过所有现有过滤器)。如果是这样,将它添加到素数列表中,减少n并添加一个新的过滤器,它将无法通过任何可被next除尽的数字。
显然,只要编译器计算出素数,这个程序的编译时间就会相对较长。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #include <iostream> #include 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> |