假设我想声明一个 local 静态常量数组,但我不知道它在编译时的初始化值,并且必须先计算它们。 例如,我有一个数组int p[100]
。我写了一个循环来填充前100个素数。在计算完这些之后,我定义了一个static const int primes[100]
,它必须由p
的值初始化。我怎么能这样做?
P.S。问题" 为什么我想声明一个本地静态const对象?"可能没有一个令人满意的答案,但我认为这不是这种情况。
P.S.S。我作为一个例子提到了素数。这不是重点。
P.S.S.S。让我们说p
有1000000名成员。那么user2079303建议的解决方案肯定值得更多的支持。
答案 0 :(得分:2)
可以在运行时初始化一个静态const数组,但有点乏味:
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 :(得分:1)
为了回避你的问题,使用模板元编程在编译时计算素数实际上是完全可行的。以下代码显示了执行此操作的可能方法。 main函数创建实例化PrimeGen类型以生成1st 100 primes的编译时std :: array。抱歉代码有点难以阅读,因为这里有很多模板样板。基本上,大多数逻辑都发生在第一个PrimeGen专业化中,它使用Eratosthenes筛来生成素数,使用以下基本公式:
从N = 100开始(尚未生成所需数量),Next = 2,空的素数列表和一个空的过滤器列表
检查Next是否为素数(即,传递所有现有过滤器)。如果是这样,将它添加到素数列表中,减少N并添加一个新的过滤器,该过滤器将无法传递可被Next整除的任何数字。
显然,当编译器计算素数时,这个程序的编译时间会相对较长。
#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;
}
答案 2 :(得分: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
计算。
答案 3 :(得分:0)
我刚刚在另一个问题中阅读了this great answer并将其弄清楚了。无需将局部变量声明为static const
。似乎只有static
足以使计算值保持在范围之外。