Cumulative Product of Template Parameter Pack - c++

I'm trying to initialise a static and constant array with the cumulative product of a template parameter pack:
template <int ...D>
class Foo
{
static const std::array<const Size, sizeof...(D)> _array;
};
template <int...D> const std::array<const int, sizeof...(D)> Foo<D...>::_array =
{ cumulative_product<D...>() };
How do I write the function cumulative_product<>(), such that it transforms D... into the cumulative product of D...? E.g.
Foo<1,2,3,4>::_array;// = {1,1*2,1*2*3,1*2*3*4} = {1,2,6,24}.
Solution: Massive thank you to #bogdan for your excellent C++14 solution, and improvements to my C++11 solution.
#include <array>
#include <iostream>
#define CPP_VERSION 11
#if CPP_VERSION >= 14
// Credit: #bogdan at http://stackoverflow.com/q/37373602/6367128
template<int... Args> constexpr std::array<int, sizeof...(Args)> cumulative_product(int seed = 1) { return{ { seed *= Args ... } }; }
#elif CPP_VERSION == 11
// Acknowledgement: Huge thank you to #bogdan for making the code more portable, concise and readable!
namespace details
{
template<int N, int i, int j, int ...Args> struct c_product_gen // N counts down to zero
{
static constexpr std::array<int, sizeof...(Args)+1> get() { return c_product_gen<N - 1, i*j, Args..., i*j>::get(); }
};
template<int i, int j, int ...Args> struct c_product_gen<0, i, j, Args...> // The end point of the template recursion
{
static constexpr std::array<int, sizeof...(Args)+1> get() { return { { j, Args... } }; }
};
}
template<int... Args> constexpr std::array<int, sizeof...(Args)> cumulative_product() { return details::c_product_gen<sizeof...(Args), 1, Args...>::get(); }
#else // CPP_VERSION < 11
template<int... Args> constexpr std::array<int, sizeof...(Args)> cumulative_product()
{
static_assert(false, "C++ version 11 or greater is required.");
return std::array<int, sizeof...(Args)>();
}
#endif
int main()
{
constexpr auto a = cumulative_product<1,2,3,4,5>();
for(auto i : a) std::cout << i << ' '; // Output: 1 2 6 24 120
std::cout << '\n';
}

#include <array>
#include <utility>
#include <cstddef>
template <int... D, std::size_t... Is>
constexpr std::array<int, sizeof...(D)> cumulative_product(std::index_sequence<Is...>)
{
static_assert(sizeof...(D), "Missing initializers");
int a[]{ D... };
for (int i = 1; i < int(sizeof...(D)); ++i)
{
a[i] *= a[i-1];
}
return {{ a[Is]... }};
}
template <int... D>
constexpr auto cumulative_product()
{
return cumulative_product<D...>(std::make_index_sequence<sizeof...(D)>{});
}
template <int... D>
struct Foo
{
static constexpr std::array<int, sizeof...(D)> _array = cumulative_product<D...>();
};
DEMO

Related

C++ "forgetting" that variable is constexpr when used as function argument

I have the following code where I am irritated by the fact that compiler is unable to see that variable passed as argument to a function is constexpr so I must use arity 0 function instead of 1 argument function.
I know this is not a compiler bug, but I wonder if there are idioms that enable to workaround this problem.
#include <array>
#include <iostream>
static constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
template <typename C, typename P, typename Y>
static constexpr void copy_if(const C& rng, P p, Y yi3ld) {
for (const auto& elem: rng) {
if (p(elem)){
yi3ld(elem);
}
}
}
// template<std::size_t N>
static constexpr auto get_evens(/* const std::array<int, N>& arr */) {
constexpr auto is_even = [](const int i) constexpr {return i % 2 == 0;};
constexpr int cnt = [/* &arr, */&is_even]() constexpr {
int cnt = 0;
auto increment = [&cnt] (const auto&){cnt++;};
copy_if(arr, is_even, increment);
return cnt;
}();
std::array<int, cnt> result{};
int idx = 0;
copy_if(arr, is_even, [&result, &idx](const auto& val){ result[idx++] = val;});
return result;
}
int main() {
// constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
for (const int i:get_evens(/* arr */)) {
std::cout << i << " " << std::endl;
}
}
If it is not obvious what I want: I would like to change get_evens signature so that it is template templated on array size N and that it takes 1 argument of type const std::array<int, N>&.
The error message when I change arr to be an function argument isn't helpful:
prog.cc:25:21: note: initializer of 'cnt' is not a constant expression
prog.cc:19:19: note: declared here
constexpr int cnt = [&arr, &is_even]()constexpr {
A function argument is never a constant expression, even if a function is used in constexpr context:
constexpr int foo(int i)
{
// i is not a constexpr
return i + 1;
}
constexpr auto i = 1;
constexpr auto j = foo(i);
To mimic a constexpr argument, use a template parameter:
template<int i>
constexpr int foo()
{
// i is constexpr
return i + 1;
}
constexpr auto i = 1;
constexpr auto j = foo<i>();
A possible solution is to use std::integer_sequence to encode integers into a type:
#include <array>
#include <iostream>
#include <type_traits>
template<typename P, typename Y, int... elements>
constexpr void copy_if_impl(P p, Y yi3ld, std::integer_sequence<int, elements...>) {
((p(elements) && (yi3ld(elements), true)), ...);
}
template<typename arr_t, typename P, typename Y>
constexpr void copy_if(P p, Y yi3ld) {
copy_if_impl(p, yi3ld, arr_t{});
}
template<typename arr_t>
constexpr auto get_evens(){
constexpr auto is_even = [](const int i) constexpr { return i % 2 == 0; };
constexpr int cnt = [&is_even]() constexpr {
int cnt = 0;
auto increment = [&cnt](const auto&) { cnt++; };
copy_if<arr_t>(is_even, increment);
return cnt;
}();
std::array<int, cnt> result{};
int idx = 0;
copy_if<arr_t>(is_even, [&result, &idx](const auto& val) {
result[idx++] = val; });
return result;
}
int main()
{
using arr = std::integer_sequence<int, 11, 22, 33, 44, 55>;
for (const int i : get_evens<arr>()) {
std::cout << i << " " << std::endl;
}
}
Addition suggested by Constantinos Glynos.
From Effective Modern C++ book by Scott Meyers, item 15, p.98:
constexpr functions can be used in contexts that demand compile-time constants. If the values of the arguments you pass to a constexpr function in such a context are known during compilation, the result will be computed during compilation. If any of the arguments’ values is not known during compilation, your code will be rejected.
When a constexpr function is called with one or more values that are not known during compilation, it acts like a normal function, computing its result at runtime. This means you don’t need two functions to perform the same operation, one for compile-time constants and one for all other values. The constexpr function does it all.
The other answer has a correct work around but I think the reasoning has nothing to do with parameters but instead to do with the lambda capture here:
constexpr int cnt = [/* &arr, */&is_even]()
Indeed we can test the various scenarios with this code:
#include <array>
#include <iostream>
template <size_t N>
constexpr int foo(const std::array<int, N>& arr) {
return [&arr] () { return arr.size(); }();
}
template <size_t N>
constexpr int bar(const std::array<int, N>& arr) {
int res{};
for (auto i : arr) {
res++;
}
return res;
}
template <size_t N>
constexpr int baz(const std::array<int, N>& arr) {
constexpr int test = [&arr] () constexpr {
return bar(arr);
}();
return test;
}
int main() {
constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
constexpr std::array<int, foo(arr)> test{};
constexpr std::array<int, bar(arr)> test2{};
constexpr std::array<int, baz(arr)> test3{};
}
Note that the line where test3 is initialized fails to compile. This, however, compiles just fine:
template <size_t N>
constexpr int baz(const std::array<int, N>& arr) {
return bar(arr);
}
So, what's the problem here? Well lambdas are really just glorified functors, and internally it'll look something like this:
struct constexpr_functor {
const std::array<int, 5>& arr;
constexpr constexpr_functor(const std::array<int, 5>& test)
: arr(test) { }
constexpr int operator()() const {
return bar(arr);
}
};
// ...
constexpr constexpr_functor t{arr};
constexpr std::array<int, t()> test3{};
Notice now that we get an error message showing the real problem:
test.cpp:36:33: note: reference to 'arr' is not a constant expression
test.cpp:33:34: note: declared here
constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
The other answer quotes Scotts Meyer's book but misinterprets the quotes. The book actually shows several examples of parameters being used in constexpr situations, but the quotes are simply saying that if you pass a non-constexpr parameter, the function can run at compile-time.
Following the Evg's suggestion, so passing the numbers as template parameters of a std::integer_sequence, but passing the integer sequence as argument of the get_evens() function, and not as template parameter, you can use the numbers directly inside get_evens().
I mean... you can simplify the get_evens() as follows (EDIT: further simplified following a suggestion from Evg (Thanks!))
template <typename T, T ... Ts>
constexpr auto get_evens (std::integer_sequence<T, Ts...> const &)
{
std::array<T, (std::size_t(!(Ts & T{1})) + ...)> result{};
std::size_t idx = 0;
((void)(Ts & 1 || (result[idx++] = Ts, true)), ...);
return result;
}
and you can use it this way
int main()
{
using arr = std::integer_sequence<int, 11, 22, 33, 44, 55>;
for ( const int i : get_evens(arr{}) )
std::cout << i << " " << std::endl;
}
#include <array>
#include <iostream>
static constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
template <typename C, typename P, typename T>
static constexpr void invoke_if(const C& rng, P p, T target) {
for (const auto& elem: rng) {
if (p(elem)){
target(elem);
}
}
}
constexpr bool is_even(int i) {
return i % 2 == 0;
}
template<std::size_t N>
constexpr std::size_t count_evens(const std::array<int, N>& arr)
{
std::size_t cnt = 0;
invoke_if(arr, is_even, [&cnt](auto&&){++cnt;});
return cnt;
}
template<std::size_t cnt, std::size_t N>
static constexpr auto get_evens(const std::array<int, N>& arr) {
std::array<int, cnt> result{};
int idx = 0;
invoke_if(arr, is_even, [&result, &idx](const auto& val){ result[idx++] = val;});
return result;
}
int main() {
// constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
for (const int i:get_evens<count_evens(arr)>(arr)) {
std::cout << i << " " << std::endl;
}
}
this works in g++, but in clang we get a problem because the begin on an array isn't properly constexpr with at least one library. Or maybe g++ violates the standard and clang does not.
template<auto t0, auto...ts>
struct ct_array:
std::array<decltype(t0) const, 1+sizeof...(ts)>,
std::integer_sequence<decltype(t0), t0, ts...>
{
ct_array():std::array<decltype(t0) const, 1+sizeof...(ts)>{{t0, ts...}} {};
};
template<class target, auto X>
struct push;
template<auto X>
struct push<void, X>{using type=ct_array<X>;};
template<auto...elems, auto X>
struct push<ct_array<elems...>, X>{using type=ct_array<elems...,X>;};
template<class target, auto X>
using push_t= typename push<target, X>::type;
template<class target>
struct pop;
template<auto x>
struct pop<ct_array<x>>{using type=void;};
template<auto x0, auto...xs>
struct pop<ct_array<x0, xs...>>{using type=ct_array<xs...>;};
template<class target>
using pop_t=typename pop<target>::type;
template<class lhs, class rhs, class F, class=void>
struct transcribe;
template<class lhs, class rhs, class F>
using transcribe_t = typename transcribe<lhs, rhs, F>::type;
template<auto l0, auto...lhs, class rhs, class F>
struct transcribe<ct_array<l0, lhs...>, rhs, F,
std::enable_if_t<F{}(l0) && sizeof...(lhs)>
>:
transcribe<pop_t<ct_array<l0, lhs...>>, push_t<rhs, l0>, F>
{};
template<auto l0, auto...lhs, class rhs, class F>
struct transcribe<ct_array<l0, lhs...>, rhs, F,
std::enable_if_t<!F{}(l0) && sizeof...(lhs)>
>:
transcribe<pop_t<ct_array<l0, lhs...>>, rhs, F>
{};
template<auto lhs, class rhs, class F>
struct transcribe<ct_array<lhs>, rhs, F, void>
{
using type=std::conditional_t< F{}(lhs), push_t<rhs, lhs>, rhs >;
};
template<class lhs, class F>
using filter_t = transcribe_t<lhs, void, F>;
// C++20
//auto is_even = [](auto i)->bool{ return !(i%2); };
struct is_even_t {
template<class T>
constexpr bool operator()(T i)const{ return !(i%2); }
};
constexpr is_even_t is_even{};
template<auto...is>
static constexpr auto get_evens(ct_array<is...>) {
return filter_t< ct_array<is...>, decltype(is_even) >{};
}
Live example.
Test code:
auto arr = ct_array<11, 22, 33, 44, 55>{};
for (const int i : get_evens(arr)) {
std::cout << i << " " << std::endl;
}

Make loop variable a constant in C++

I am currently creating arithmetic operators libraries for high level synthesis.
For this, I am also creating a library to manipulate bits and bit vectors like it would be done in VHDL. To make my libraries synthesizable, nearly everything must be resolved at compile time.
However, I have an issue with loops.
Indeed, I would like to be able to write things like that:
const int N = 5;
for(int i = 0; i < N-2; i++) {
x.bit<i+2>() = x.bit<i>();
}
Of course, it does not compile since i is a variable and not a constant determined at compile time.
However, N being a constant, this code is strictly equivalent to:
x.bit<2>() = x.bit<0>();
x.bit<3>() = x.bit<1>();
x.bit<4>() = x.bit<2>();
which compiles and works perfectly.
Is there a way to make the compiler (gcc in my case) unroll the loop since N is constant? Or to define a macro or a constexpr which could do it with a clean syntax? This would be the equivalent of for generate in VHDL.
While constexpr has got much more powerful in C++14/17 it is not yet possible to mix this kind of compile time / template code with an ordinary loop. There is some talk of introducing a construct that might enable that in a future version of C++. For now you have a few choices, either recursive calls to a function with an integer template argument or probably simpler in this case a C++17 fold expression. You could also use C++11 variadic template expansion to get a similar result to fold expressions in this example, though fold expressions are more powerful.
Just saw your comment about being stuck with C++11, you're probably better off using the recursive function approach I think. I've added that approach to the example.
If you were able to use C++14 you might also want to consider moving entirely into constexpr function / type land so your bit<I>() function would not be templated but would be just a constexpr function bit(i). You could then use normal functions and loops. Given the C++11 restrictions on constexpr functions that is probably less useful in your case however. I've added an example using that approach.
#include <iostream>
#include <utility>
template <size_t N>
struct bits {
bool bs[N];
template <size_t I>
constexpr const bool& bit() const {
return bs[I];
}
template <size_t I>
constexpr bool& bit() {
return bs[I];
}
constexpr bool bit(int i) const { return bs[i]; }
constexpr void bit(int i, bool x) { bs[i] = x; }
};
// Using C++17 fold expressions
template <size_t N, size_t... Is>
constexpr bits<N> set_bits_helper(bits<N> x, std::index_sequence<Is...>) {
((x.bit<Is + 2>() = x.bit<Is>()), ...);
return x;
}
template <size_t N>
constexpr bits<N> set_bits(bits<N> x) {
return set_bits_helper(x, std::make_index_sequence<N - 2>{});
}
// Using recursive template function, should work on C++11
template <size_t I, size_t N>
constexpr bits<N> set_bits_recursive_helper(bits<N> x, std::integral_constant<size_t, I>) {
x.bit<N - I>() = x.bit<N - I - 2>();
return set_bits_recursive_helper(x, std::integral_constant<size_t, I - 1>{});
}
template <size_t N>
constexpr bits<N> set_bits_recursive_helper(bits<N> x, std::integral_constant<size_t, 0>) { return x; }
template <size_t N>
constexpr bits<N> set_bits_recursive(bits<N> x) {
return set_bits_recursive_helper(x, std::integral_constant<size_t, N - 2>{});
}
// Using non template constexpr functions
template <size_t N>
constexpr bits<N> set_bits_constexpr(bits<N> x) {
for (int i = 0; i < N - 2; ++i) {
x.bit(i + 2, x.bit(i));
}
return x;
}
// Test code to show usage
template <size_t N>
void print_bits(const bits<N>& x) {
for (auto b : x.bs) {
std::cout << b << ", ";
}
std::cout << '\n';
}
void test_set_bits() {
constexpr bits<8> x{ 1, 0 };
print_bits(x);
constexpr auto y = set_bits(x);
static_assert(y.bit<2>() == x.bit<0>());
print_bits(y);
}
void test_set_bits_recursive() {
constexpr bits<8> x{ 1, 0 };
print_bits(x);
constexpr auto y = set_bits_recursive(x);
static_assert(y.bit<2>() == x.bit<0>());
print_bits(y);
}
void test_set_bits_constexpr() {
constexpr bits<8> x{ 1, 0 };
print_bits(x);
constexpr auto y = set_bits_constexpr(x);
static_assert(y.bit<2>() == x.bit<0>());
print_bits(y);
}
int main() {
test_set_bits();
test_set_bits_recursive();
test_set_bits_constexpr();
}
Also without std::integer_sequence (but I suggest to implement a substitute and use it), in C++11 you can use template partial specialization.
I mean that you can implement something like
template <int I, int Sh, int N>
struct shiftVal
{
template <typename T>
static int func (T & t)
{ return t.template bit<I+Sh>() = t.template bit<I>(),
shiftVal<I+1, Sh, N>::func(t); }
};
template <int I, int Sh>
struct shiftVal<I, Sh, I>
{
template <typename T>
static int func (T &)
{ return 0; }
};
and your cycle become
shiftVal<0, 2, N-2>::func(x);
The following is a full working example
#include <array>
#include <iostream>
template <std::size_t N>
struct foo
{
std::array<int, N> arr;
template <int I>
int & bit ()
{ return arr[I]; }
};
template <int I, int Sh, int N>
struct shiftVal
{
template <typename T>
static int func (T & t)
{ return t.template bit<I+Sh>() = t.template bit<I>(),
shiftVal<I+1, Sh, N>::func(t); }
};
template <int I, int Sh>
struct shiftVal<I, Sh, I>
{
template <typename T>
static int func (T &)
{ return 0; }
};
int main ()
{
foo<10U> f { { { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 } } };
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
shiftVal<0, 2, 10-2>::func(f);
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
Nobody else produce an example based on a C++11 simulation of std::integer_sequence (as suggested by W.F., Passer By and Sopel and the simpler solution, IMHO) so I propose the following one (of std::index_sequence and std::make_index_sequence in reality: simulate std::integer_sequence is more complicated)
template <std::size_t ...>
struct indexSequence
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSequenceHelper : public indexSequenceHelper<N-1U, N-1U, Next...>
{ };
template <std::size_t ... Next>
struct indexSequenceHelper<0U, Next ... >
{ using type = indexSequence<Next ... >; };
template <std::size_t N>
using makeIndexSequence = typename indexSequenceHelper<N>::type;
So a function (with function helper) to reproduce the asked loop can be written as
template
void shiftValHelper (T & t, indexSequence<Is...> const &)
{
using unused = int[];
(void)unused { 0,
(t.template bit<Is+Sh>() = t.template bit<Is>(), 0)... };
}
template <std::size_t Sh, std::size_t N, typename T>
void shiftVal (T & t)
{ shiftValHelper<Sh>(t, makeIndexSequence<N>{}); }
and called ad follows
shiftVal<2, N-2>(x);
The following is a full working example
#include <array>
#include <iostream>
template <std::size_t ...>
struct indexSequence
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSequenceHelper : public indexSequenceHelper<N-1U, N-1U, Next...>
{ };
template <std::size_t ... Next>
struct indexSequenceHelper<0U, Next ... >
{ using type = indexSequence<Next ... >; };
template <std::size_t N>
using makeIndexSequence = typename indexSequenceHelper<N>::type;
template <std::size_t N>
struct foo
{
std::array<int, N> arr;
template <std::size_t I>
int & bit ()
{ return arr[I]; }
};
template <std::size_t Sh, typename T, std::size_t ... Is>
void shiftValHelper (T & t, indexSequence<Is...> const &)
{
using unused = int[];
(void)unused { 0,
(t.template bit<Is+Sh>() = t.template bit<Is>(), 0)... };
}
template <std::size_t Sh, std::size_t N, typename T>
void shiftVal (T & t)
{ shiftValHelper<Sh>(t, makeIndexSequence<N>{}); }
int main ()
{
foo<10U> f { { { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 } } };
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
shiftVal<2, 10-2>(f);
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
}

Filling an array during compilation [duplicate]

Hello i'm learning C++11, I'm wondering how to make a constexpr 0 to n array, for example:
n = 5;
int array[] = {0 ... n};
so array may be {0, 1, 2, 3, 4, 5}
In C++14 it can be easily done with a constexpr constructor and a loop:
#include <iostream>
template<int N>
struct A {
constexpr A() : arr() {
for (auto i = 0; i != N; ++i)
arr[i] = i;
}
int arr[N];
};
int main() {
constexpr auto a = A<4>();
for (auto x : a.arr)
std::cout << x << '\n';
}
Unlike those answers in the comments to your question, you can do this without compiler extensions.
#include <iostream>
template<int N, int... Rest>
struct Array_impl {
static constexpr auto& value = Array_impl<N - 1, N, Rest...>::value;
};
template<int... Rest>
struct Array_impl<0, Rest...> {
static constexpr int value[] = { 0, Rest... };
};
template<int... Rest>
constexpr int Array_impl<0, Rest...>::value[];
template<int N>
struct Array {
static_assert(N >= 0, "N must be at least 0");
static constexpr auto& value = Array_impl<N>::value;
Array() = delete;
Array(const Array&) = delete;
Array(Array&&) = delete;
};
int main() {
std::cout << Array<4>::value[3]; // prints 3
}
Based on #Xeo's excellent idea, here is an approach that lets you fill an array of
constexpr std::array<T, N> a = { fun(0), fun(1), ..., fun(N-1) };
where T is any literal type (not just int or other valid non-type template parameter types), but also double, or std::complex (from C++14 onward)
where fun() is any constexpr function
which is supported by std::make_integer_sequence from C++14 onward, but easily implemented today with both g++ and Clang (see Live Example at the end of the answer)
I use #JonathanWakely 's implementation at GitHub (Boost License)
Here is the code
template<class Function, std::size_t... Indices>
constexpr auto make_array_helper(Function f, std::index_sequence<Indices...>)
-> std::array<typename std::result_of<Function(std::size_t)>::type, sizeof...(Indices)>
{
return {{ f(Indices)... }};
}
template<int N, class Function>
constexpr auto make_array(Function f)
-> std::array<typename std::result_of<Function(std::size_t)>::type, N>
{
return make_array_helper(f, std::make_index_sequence<N>{});
}
constexpr double fun(double x) { return x * x; }
int main()
{
constexpr auto N = 10;
constexpr auto a = make_array<N>(fun);
std::copy(std::begin(a), std::end(a), std::ostream_iterator<double>(std::cout, ", "));
}
Live Example
Use C++14 integral_sequence, or its invariant index_sequence
#include <iostream>
template< int ... I > struct index_sequence{
using type = index_sequence;
using value_type = int;
static constexpr std::size_t size()noexcept{ return sizeof...(I); }
};
// making index_sequence
template< class I1, class I2> struct concat;
template< int ...I, int ...J>
struct concat< index_sequence<I...>, index_sequence<J...> >
: index_sequence< I ... , ( J + sizeof...(I) )... > {};
template< int N > struct make_index_sequence_impl;
template< int N >
using make_index_sequence = typename make_index_sequence_impl<N>::type;
template< > struct make_index_sequence_impl<0> : index_sequence<>{};
template< > struct make_index_sequence_impl<1> : index_sequence<0>{};
template< int N > struct make_index_sequence_impl
: concat< make_index_sequence<N/2>, make_index_sequence<N - N/2> > {};
// now, we can build our structure.
template < class IS > struct mystruct_base;
template< int ... I >
struct mystruct_base< index_sequence< I ... > >
{
static constexpr int array[]{I ... };
};
template< int ... I >
constexpr int mystruct_base< index_sequence<I...> >::array[] ;
template< int N > struct mystruct
: mystruct_base< make_index_sequence<N > >
{};
int main()
{
mystruct<20> ms;
//print
for(auto e : ms.array)
{
std::cout << e << ' ';
}
std::cout << std::endl;
return 0;
}
output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
UPDATE:
You may use std::array:
template< int ... I >
static constexpr std::array< int, sizeof...(I) > build_array( index_sequence<I...> ) noexcept
{
return std::array<int, sizeof...(I) > { I... };
}
int main()
{
std::array<int, 20> ma = build_array( make_index_sequence<20>{} );
for(auto e : ma) std::cout << e << ' ';
std::cout << std::endl;
}
#include <array>
#include <iostream>
template<int... N>
struct expand;
template<int... N>
struct expand<0, N...>
{
constexpr static std::array<int, sizeof...(N) + 1> values = {{ 0, N... }};
};
template<int L, int... N> struct expand<L, N...> : expand<L-1, L, N...> {};
template<int... N>
constexpr std::array<int, sizeof...(N) + 1> expand<0, N...>::values;
int main()
{
std::cout << expand<100>::values[9];
}
For std::array in C++17,
constexpr function are also accepted
Note that the var 'arr' must be initialized by constexpr required.
(initialize: same meaning with answer of #abyx)
#include <array>
constexpr std::array<int, 3> get_array()
{
std::array<int, 3> arr{0};
arr[0] = 9;
return arr;
}
static_assert(get_array().size() == 3);
With C++17 this can be done easily as std::array::begin is marked constexpr.
template<std::size_t N> std::array<int, N + 1> constexpr make_array()
{
std::array<int, N + 1> tempArray{};
int count = 0;
for(int &elem:tempArray)
{
elem = count++;
}
return tempArray;
}
int main()
{
//-------------------------------vv------>pass the size here
constexpr auto arr = make_array<5>();
//lets confirm if all objects have the expected value
for(const auto &elem: arr)
{
std::cout << elem << std::endl; //prints 1 2 3 4 5 with newline in between
}
}
Demo
Using boost preprocessor, it's very simple:
#include <cstdio>
#include <cstddef>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/comma_if.hpp>
#define IDENTITY(z,n,dummy) BOOST_PP_COMMA_IF(n) n
#define INITIALIZER_n(n) { BOOST_PP_REPEAT(n,IDENTITY,~) }
int main(int argc, char* argv[])
{
int array[] = INITIALIZER_n(25);
for(std::size_t i = 0; i < sizeof(array)/sizeof(array[0]); ++i)
printf("%d ",array[i]);
return 0;
}
OUTPUT:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Consider boost::mpl::range_c<int, 0, N> instead.

Create N-element constexpr array in C++11

Hello i'm learning C++11, I'm wondering how to make a constexpr 0 to n array, for example:
n = 5;
int array[] = {0 ... n};
so array may be {0, 1, 2, 3, 4, 5}
In C++14 it can be easily done with a constexpr constructor and a loop:
#include <iostream>
template<int N>
struct A {
constexpr A() : arr() {
for (auto i = 0; i != N; ++i)
arr[i] = i;
}
int arr[N];
};
int main() {
constexpr auto a = A<4>();
for (auto x : a.arr)
std::cout << x << '\n';
}
Unlike those answers in the comments to your question, you can do this without compiler extensions.
#include <iostream>
template<int N, int... Rest>
struct Array_impl {
static constexpr auto& value = Array_impl<N - 1, N, Rest...>::value;
};
template<int... Rest>
struct Array_impl<0, Rest...> {
static constexpr int value[] = { 0, Rest... };
};
template<int... Rest>
constexpr int Array_impl<0, Rest...>::value[];
template<int N>
struct Array {
static_assert(N >= 0, "N must be at least 0");
static constexpr auto& value = Array_impl<N>::value;
Array() = delete;
Array(const Array&) = delete;
Array(Array&&) = delete;
};
int main() {
std::cout << Array<4>::value[3]; // prints 3
}
Based on #Xeo's excellent idea, here is an approach that lets you fill an array of
constexpr std::array<T, N> a = { fun(0), fun(1), ..., fun(N-1) };
where T is any literal type (not just int or other valid non-type template parameter types), but also double, or std::complex (from C++14 onward)
where fun() is any constexpr function
which is supported by std::make_integer_sequence from C++14 onward, but easily implemented today with both g++ and Clang (see Live Example at the end of the answer)
I use #JonathanWakely 's implementation at GitHub (Boost License)
Here is the code
template<class Function, std::size_t... Indices>
constexpr auto make_array_helper(Function f, std::index_sequence<Indices...>)
-> std::array<typename std::result_of<Function(std::size_t)>::type, sizeof...(Indices)>
{
return {{ f(Indices)... }};
}
template<int N, class Function>
constexpr auto make_array(Function f)
-> std::array<typename std::result_of<Function(std::size_t)>::type, N>
{
return make_array_helper(f, std::make_index_sequence<N>{});
}
constexpr double fun(double x) { return x * x; }
int main()
{
constexpr auto N = 10;
constexpr auto a = make_array<N>(fun);
std::copy(std::begin(a), std::end(a), std::ostream_iterator<double>(std::cout, ", "));
}
Live Example
Use C++14 integral_sequence, or its invariant index_sequence
#include <iostream>
template< int ... I > struct index_sequence{
using type = index_sequence;
using value_type = int;
static constexpr std::size_t size()noexcept{ return sizeof...(I); }
};
// making index_sequence
template< class I1, class I2> struct concat;
template< int ...I, int ...J>
struct concat< index_sequence<I...>, index_sequence<J...> >
: index_sequence< I ... , ( J + sizeof...(I) )... > {};
template< int N > struct make_index_sequence_impl;
template< int N >
using make_index_sequence = typename make_index_sequence_impl<N>::type;
template< > struct make_index_sequence_impl<0> : index_sequence<>{};
template< > struct make_index_sequence_impl<1> : index_sequence<0>{};
template< int N > struct make_index_sequence_impl
: concat< make_index_sequence<N/2>, make_index_sequence<N - N/2> > {};
// now, we can build our structure.
template < class IS > struct mystruct_base;
template< int ... I >
struct mystruct_base< index_sequence< I ... > >
{
static constexpr int array[]{I ... };
};
template< int ... I >
constexpr int mystruct_base< index_sequence<I...> >::array[] ;
template< int N > struct mystruct
: mystruct_base< make_index_sequence<N > >
{};
int main()
{
mystruct<20> ms;
//print
for(auto e : ms.array)
{
std::cout << e << ' ';
}
std::cout << std::endl;
return 0;
}
output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
UPDATE:
You may use std::array:
template< int ... I >
static constexpr std::array< int, sizeof...(I) > build_array( index_sequence<I...> ) noexcept
{
return std::array<int, sizeof...(I) > { I... };
}
int main()
{
std::array<int, 20> ma = build_array( make_index_sequence<20>{} );
for(auto e : ma) std::cout << e << ' ';
std::cout << std::endl;
}
#include <array>
#include <iostream>
template<int... N>
struct expand;
template<int... N>
struct expand<0, N...>
{
constexpr static std::array<int, sizeof...(N) + 1> values = {{ 0, N... }};
};
template<int L, int... N> struct expand<L, N...> : expand<L-1, L, N...> {};
template<int... N>
constexpr std::array<int, sizeof...(N) + 1> expand<0, N...>::values;
int main()
{
std::cout << expand<100>::values[9];
}
For std::array in C++17,
constexpr function are also accepted
Note that the var 'arr' must be initialized by constexpr required.
(initialize: same meaning with answer of #abyx)
#include <array>
constexpr std::array<int, 3> get_array()
{
std::array<int, 3> arr{0};
arr[0] = 9;
return arr;
}
static_assert(get_array().size() == 3);
With C++17 this can be done easily as std::array::begin is marked constexpr.
template<std::size_t N> std::array<int, N + 1> constexpr make_array()
{
std::array<int, N + 1> tempArray{};
int count = 0;
for(int &elem:tempArray)
{
elem = count++;
}
return tempArray;
}
int main()
{
//-------------------------------vv------>pass the size here
constexpr auto arr = make_array<5>();
//lets confirm if all objects have the expected value
for(const auto &elem: arr)
{
std::cout << elem << std::endl; //prints 1 2 3 4 5 with newline in between
}
}
Demo
Using boost preprocessor, it's very simple:
#include <cstdio>
#include <cstddef>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/comma_if.hpp>
#define IDENTITY(z,n,dummy) BOOST_PP_COMMA_IF(n) n
#define INITIALIZER_n(n) { BOOST_PP_REPEAT(n,IDENTITY,~) }
int main(int argc, char* argv[])
{
int array[] = INITIALIZER_n(25);
for(std::size_t i = 0; i < sizeof(array)/sizeof(array[0]); ++i)
printf("%d ",array[i]);
return 0;
}
OUTPUT:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Consider boost::mpl::range_c<int, 0, N> instead.

C++11: Compile Time Calculation of Array

Suppose I have some constexpr function f:
constexpr int f(int x) { ... }
And I have some const int N known at compile time:
Either
#define N ...;
or
const int N = ...;
as needed by your answer.
I want to have an int array X:
int X[N] = { f(0), f(1), f(2), ..., f(N-1) }
such that the function is evaluated at compile time, and the entries in X are calculated by the compiler and the results are placed in the static area of my application image exactly as if I had used integer literals in my X initializer list.
Is there some way I can write this? (For example with templates or macros and so on)
Best I have: (Thanks to Flexo)
#include <iostream>
#include <array>
using namespace std;
constexpr int N = 10;
constexpr int f(int x) { return x*2; }
typedef array<int, N> A;
template<int... i> constexpr A fs() { return A{{ f(i)... }}; }
template<int...> struct S;
template<int... i> struct S<0,i...>
{ static constexpr A gs() { return fs<0,i...>(); } };
template<int i, int... j> struct S<i,j...>
{ static constexpr A gs() { return S<i-1,i,j...>::gs(); } };
constexpr auto X = S<N-1>::gs();
int main()
{
cout << X[3] << endl;
}
There is a pure C++11 (no boost, no macros too) solution to this problem. Using the same trick as this answer we can build a sequence of numbers and unpack them to call f to construct a std::array:
#include <array>
#include <algorithm>
#include <iterator>
#include <iostream>
template<int ...>
struct seq { };
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
constexpr int f(int n) {
return n;
}
template <int N>
class array_thinger {
typedef typename gens<N>::type list;
template <int ...S>
static constexpr std::array<int,N> make_arr(seq<S...>) {
return std::array<int,N>{{f(S)...}};
}
public:
static constexpr std::array<int,N> arr = make_arr(list());
};
template <int N>
constexpr std::array<int,N> array_thinger<N>::arr;
int main() {
std::copy(begin(array_thinger<10>::arr), end(array_thinger<10>::arr),
std::ostream_iterator<int>(std::cout, "\n"));
}
(Tested with g++ 4.7)
You could skip std::array entirely with a bit more work, but I think in this instance it's cleaner and simpler to just use std::array.
You can also do this recursively:
#include <array>
#include <functional>
#include <algorithm>
#include <iterator>
#include <iostream>
constexpr int f(int n) {
return n;
}
template <int N, int ...Vals>
constexpr
typename std::enable_if<N==sizeof...(Vals),std::array<int, N>>::type
make() {
return std::array<int,N>{{Vals...}};
}
template <int N, int ...Vals>
constexpr
typename std::enable_if<N!=sizeof...(Vals), std::array<int,N>>::type
make() {
return make<N, Vals..., f(sizeof...(Vals))>();
}
int main() {
const auto arr = make<10>();
std::copy(begin(arr), end(arr), std::ostream_iterator<int>(std::cout, "\n"));
}
Which is arguably simpler.
Boost.Preprocessor can help you. The restriction, however, is that you have to use integral literal such as 10 instead of N (even be it compile-time constant):
#include <iostream>
#include <boost/preprocessor/repetition/enum.hpp>
#define VALUE(z, n, text) f(n)
//ideone doesn't support Boost for C++11, so it is C++03 example,
//so can't use constexpr in the function below
int f(int x) { return x * 10; }
int main() {
int const a[] = { BOOST_PP_ENUM(10, VALUE, ~) }; //N = 10
std::size_t const n = sizeof(a)/sizeof(int);
std::cout << "count = " << n << "\n";
for(std::size_t i = 0 ; i != n ; ++i )
std::cout << a[i] << "\n";
return 0;
}
Output (ideone):
count = 10
0
10
20
30
40
50
60
70
80
90
The macro in the following line:
int const a[] = { BOOST_PP_ENUM(10, VALUE, ~) };
expands to this:
int const a[] = {f(0), f(1), ... f(9)};
A more detail explanation is here:
BOOST_PP_ENUM
If you want the array to live in static memory, you could try this:
template<class T> struct id { typedef T type; };
template<int...> struct int_pack {};
template<int N, int...Tail> struct make_int_range
: make_int_range<N-1,N-1,Tail...> {};
template<int...Tail> struct make_int_range<0,Tail...>
: id<int_pack<Tail...>> {};
#include <array>
constexpr int f(int n) { return n*(n+1)/2; }
template<class Indices = typename make_int_range<10>::type>
struct my_lookup_table;
template<int...Indices>
struct my_lookup_table<int_pack<Indices...>>
{
static const int size = sizeof...(Indices);
typedef std::array<int,size> array_type;
static const array_type& get()
{
static const array_type arr = {{f(Indices)...}};
return arr;
}
};
#include <iostream>
int main()
{
auto& lut = my_lookup_table<>::get();
for (int i : lut)
std::cout << i << std::endl;
}
If you want a local copy of the array to work on, simply remove the ampersand.
There are quite a few great answers here. The question and tags specify c++11, but as a few years have passed, some (like myself) stumbling upon this question may be open to using c++14. If so, it is possible to do this very cleanly and concisely using std::integer_sequence; moreover, it can be used to instantiate much longer arrays, since the current "Best I Have" is limited by recursion depth.
constexpr std::size_t f(std::size_t x) { return x*x; } // A constexpr function
constexpr std::size_t N = 5; // Length of array
using TSequence = std::make_index_sequence<N>;
static_assert(std::is_same<TSequence, std::integer_sequence<std::size_t, 0, 1, 2, 3, 4>>::value,
"Make index sequence uses std::size_t and produces a parameter pack from [0,N)");
using TArray = std::array<std::size_t,N>;
// When you call this function with a specific std::integer_sequence,
// the parameter pack i... is used to deduce the the template parameter
// pack. Once this is known, this parameter pack is expanded in
// the body of the function, calling f(i) for each i in [0,N).
template<std::size_t...i>
constexpr TArray
get_array(std::integer_sequence<std::size_t,i...>)
{
return TArray{{ f(i)... }};
}
int main()
{
constexpr auto s = TSequence();
constexpr auto a = get_array(s);
for (const auto &i : a) std::cout << i << " "; // 0 1 4 9 16
return EXIT_SUCCESS;
}
I slightly extended the answer from Flexo and Andrew Tomazos so that the user can specify the computational range and the function to be evaluated.
#include <array>
#include <iostream>
#include <iomanip>
template<typename ComputePolicy, int min, int max, int ... expandedIndices>
struct ComputeEngine
{
static const int lengthOfArray = max - min + sizeof... (expandedIndices) + 1;
typedef std::array<typename ComputePolicy::ValueType, lengthOfArray> FactorArray;
static constexpr FactorArray compute( )
{
return ComputeEngine<ComputePolicy, min, max - 1, max, expandedIndices...>::compute( );
}
};
template<typename ComputePolicy, int min, int ... expandedIndices>
struct ComputeEngine<ComputePolicy, min, min, expandedIndices...>
{
static const int lengthOfArray = sizeof... (expandedIndices) + 1;
typedef std::array<typename ComputePolicy::ValueType, lengthOfArray> FactorArray;
static constexpr FactorArray compute( )
{
return FactorArray { { ComputePolicy::compute( min ), ComputePolicy::compute( expandedIndices )... } };
}
};
/// compute 1/j
struct ComputePolicy1
{
typedef double ValueType;
static constexpr ValueType compute( int i )
{
return i > 0 ? 1.0 / i : 0.0;
}
};
/// compute j^2
struct ComputePolicy2
{
typedef int ValueType;
static constexpr ValueType compute( int i )
{
return i * i;
}
};
constexpr auto factors1 = ComputeEngine<ComputePolicy1, 4, 7>::compute( );
constexpr auto factors2 = ComputeEngine<ComputePolicy2, 3, 9>::compute( );
int main( void )
{
using namespace std;
cout << "Values of factors1" << endl;
for ( int i = 0; i < factors1.size( ); ++i )
{
cout << setw( 4 ) << i << setw( 15 ) << factors1[i] << endl;
}
cout << "------------------------------------------" << endl;
cout << "Values of factors2" << endl;
for ( int i = 0; i < factors2.size( ); ++i )
{
cout << setw( 4 ) << i << setw( 15 ) << factors2[i] << endl;
}
return 0;
}
Here's a more concise answer where you explicitly declare the elements in the original sequence.
#include <array>
constexpr int f(int i) { return 2 * i; }
template <int... Ts>
struct sequence
{
using result = sequence<f(Ts)...>;
static std::array<int, sizeof...(Ts)> apply() { return {{Ts...}}; }
};
using v1 = sequence<1, 2, 3, 4>;
using v2 = typename v1::result;
int main()
{
auto x = v2::apply();
return 0;
}
How about this one?
#include <array>
#include <iostream>
constexpr int f(int i) { return 2 * i; }
template <int N, int... Ts>
struct t { using type = typename t<N - 1, Ts..., 101 - N>::type; };
template <int... Ts>
struct t<0u, Ts...>
{
using type = t<0u, Ts...>;
static std::array<int, sizeof...(Ts)> apply() { return {{f(Ts)...}}; }
};
int main()
{
using v = typename t<100>::type;
auto x = v::apply();
}
I don't think that's the best way to do this, but one can try somewhat like this:
#include <array>
#include <iostream>
#include <numbers>
constexpr auto pi{std::numbers::pi_v<long double>};
template <typename T>
struct fun
{
T v;
explicit constexpr fun(T a) : v{a * a} {}
};
template <size_t N, typename T, typename F>
struct pcl_arr
{
std::array<T, N> d;
explicit constexpr pcl_arr()
: d{}
{
for (size_t i{}; i < N; d[i] = !i ? 0. : F(pi + i).v, ++i);
}
};
int main()
{
using yummy = pcl_arr<10, long double, fun<long double>>;
constexpr yummy pies;
std::array cloned_pies{pies.d};
// long double comparison is unsafe
// it's just for the sake of example
static_assert(pies.d[0] == 0.);
for (const auto & pie : pies.d) { std::cout << pie << ' '; } std::cout << '\n';
for (const auto & pie : cloned_pies) { std::cout << pie << ' '; } std::cout << '\n';
return 0;
}
godbolt.org x86-x64 gcc 11.2 -Wall -O3 -std=c++20 output:
0 17.1528 26.436 37.7192 51.0023 66.2855 83.5687 102.852 124.135 147.418
0 17.1528 26.436 37.7192 51.0023 66.2855 83.5687 102.852 124.135 147.418