Это может быть для массивов фиксированного размера:
int a[] = { foo<0>::value, foo<1>::value, ... };
Массивы произвольного размера, однако, не могут быть выполнены без метапрограммирования препроцессора - Boost.Preprocessor может помочь здесь.
Еще одна вещь, на которую вы могли бы обратить внимание, это последовательности во время компиляции целочисленных констант, например, используя Boost.MPL :
template<int n>
struct squares {
typedef typename squares<n-1>::type seq;
typedef typename boost::mpl::integral_c<int, n*n>::type val;
typedef typename boost::mpl::push_back<seq, val>::type type;
};
template<>
struct squares<1> {
typedef boost::mpl::vector_c<int, 1>::type type;
};
// ...
typedef squares<3>::type sqr;
std::cout << boost::mpl::at_c<sqr, 0>::type::value << std::endl; // 1
std::cout << boost::mpl::at_c<sqr, 1>::type::value << std::endl; // 4
std::cout << boost::mpl::at_c<sqr, 2>::type::value << std::endl; // 9
(Обратите внимание, что это возможно сделать более элегантно с использованием алгоритмов MPL)
Если вас интересует тема времени компиляции, книги "Современный дизайн C ++" (основы TMP) и "Метапрограммирование шаблонов C ++" (в основном, MPL подробно объясняется ) стоит посмотреть.