Question: Here is a code snippet illustrating my question:

```
const float D    = 0.1F;
const float A[4] = {sin(0*D), sin(1*D), sin(2*D), sin(3*D)};

```

Imagine that global array `A` is much longer and you don't want to do all of this repetitive typing. Is there a shorter way to initialize array A at compile or initialization time, i.e. without having to write initialization function and call it somewhere in my program?

Answer: 
You could initialize A during dynamic initialization time as follows:

```
const float *init_a(float x_)
{
  static float data[4];
  for(unsigned i=0; i<4; ++i)
    data[i]=sin(i*x_);
  return data;
}

const float D=0.1f;
const float *A=init_a(D);

```
This first part is obsolete in C++14, but not long:

```
template<unsigned...>struct indexes { using type=indexes; };
template<unsigned Max, unsigned...Is>struct make_indexes:make_indexes<Max-1,Max-1,Is...>{};
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
template<unsigned Max>using make_indexes_t=typename make_indexes<Max>::type;

```

this is some template meta programming that lets us create and pass around bundles of indexes.

Then some code to generate the array:

```
namespace details {
  template<std::size_t N, unsigned...Is>
  std::array<float, N> poly_sin(float src, indexes<Is...>) {
    return { (Is*sin(src))... };
  }
}

template<std::size_t N>
std::array<float, N> poly_sin(float src) {
  return details::poly_sin<N>( src, make_indexes_t<N>{} );
}

```

The first method takes `indexes<Is...>` and we plan that `Is...` is `0, 1, 2, ..., N-1`. It then expands the parameter pack into a `std::array` of the right size.

`make_indexes_t<N>{}` expands (at compile time) to `indexes<0, 1, 2, ..., N-1>{}`, which is then passed to `details::poly_sin`, which then can deduce the `Is...` and use them within itself.

And point of use:

```
const float D    = 0.1F;
const auto A = poly_sin<4>(D);

```

if you had a `constexpr` `sin` function, you could even make `poly_sin` a `constexpr` function and have it basically guaranteed to be evaluated at compile time.

If this is the case, make `D` `constexpr` and same with the two `poly_sin` functions.

As written, this occurs at dynamic initialization time.

While it appears that the array is copied twice, RVO elision means that any decent compiler will directly construct it in `A`.

If you want to be able to do this in general, first start with the above `indexes` code. Then add this:

```
template<class Sig>using result_of_t=typename std::result_of<Sig>::type;
namespace details {
  template<std::size_t N, class F, unsigned... Is>
  std::array< result_of_t< F(unsigned) >, N >
  make_array( F&& f, indexes<Is...> ) {
    return { f( Is )... };
  }
}
template<std::size_t N, class F>
std::array< result_of_t< F(unsigned) >, N >
make_array( F&& f ) {
  return details::make_array( std::forward<F>(f), make_indexes_t<N>{} );
}

const auto A = make_array<4>( [](unsigned i){ return float(i*sin(D)); } );

```

which uses a lambda to pass in the code that is repeated to build the array. Sadly, lambdas are not by default `constexpr` so you cannot do it at compile time.