Programmatically create static arrays at compile time in C++
One can define a static array at compile time as follows:
const std::size_t size = 5;
unsigned int list[size] = { 1, 2, 3, 4, 5 };
Question 1 - Is it possible by using various kinds of metaprogramming techniques to assign these values "programmatically" at compile time?
Question 2 - Assuming all the values in the array are to be the same barr a few, is it possible to selectively assign values at compile time in a programmatic manner?
eg:
const std::size_t size = 7;
unsigned int list[size] = { 0, 0, 2, 3, 0, 0, 0 };
UPDATE: Georg Fritzsche's solution is amazing, needs a little work to get it compiling on msvc and intel compilers, but nonetheless a very interesting approach to the problem.
The closest you can get is using C++0x features to initialize local or member arrays of templates from a variadic template argument list.
This is of course limited by the maximum template instantiation depth and wether that actually makes a notable difference in your case would have to be measured.
Example:
template<unsigned... args> struct ArrayHolder {
static const unsigned data[sizeof...(args)];
};
template<unsigned... args>
const unsigned ArrayHolder<args...>::data[sizeof...(args)] = { args... };
template<size_t N, template<size_t> class F, unsigned... args>
struct generate_array_impl {
typedef typename generate_array_impl<N-1, F, F<N>::value, args...>::result result;
};
template<template<size_t> class F, unsigned... args>
struct generate_array_impl<0, F, args...> {
typedef ArrayHolder<F<0>::value, args...> result;
};
template<size_t N, template<size_t> class F>
struct generate_array {
typedef typename generate_array_impl<N-1, F>::result result;
};
Usage for your 1..5
case:
template<size_t index> struct MetaFunc {
enum { value = index + 1 };
};
void test() {
const size_t count = 5;
typedef generate_array<count, MetaFunc>::result A;
for (size_t i=0; i<count; ++i)
std::cout << A::data[i] << "n";
}
Well your requirements are so vague it's difficult to do anything about them... The main issue is of course: where do those value come from ?
Anyway a build in C++ can be thought of as 4 steps:
If you wish to rule out the script generation, then you're left with 2 alternatives: Preprocessing and Meta-template programming.
There is just no way I know of for meta-template programming to do the trick here, because as far as I know it's not possible to concatenate two arrays at compile time. Thus we are left with the savior of the day: Preprocessor Programming
I would suggest using a full-fledged library to help us out: Boost.Preprocessor.
Of particular interest here:
Now if only we knew where to pick the values from, we could give more meaningful examples.
How about building a nested struct using templates, and casting that as an array of the right type. The example below works for me, but I have a feeling I'm either treading in or walking very close to undefined behaviour.
#include <iostream>
template<int N>
struct NestedStruct
{
NestedStruct<N-1> contained;
int i;
NestedStruct<N>() : i(N) {}
};
template<>
struct NestedStruct<0>
{
int i;
NestedStruct<0>() : i(0) {}
};
int main()
{
NestedStruct<10> f;
int *array = reinterpret_cast<int*>(&f);
for(unsigned int i=0;i<10;++i)
{
std::cout<<array[i]<<std::endl;
}
}
And of course you could argue that the array is not initialised at compile time (which I think is impossible) but the values that will go into the array are calculated at compile time, and you can access them as you would a normal array... I think that's as close as you can get.
链接地址: http://www.djcxy.com/p/62690.html上一篇: 使用c ++模板的2s电源阵列