Is it possible to initialize const std :: array with repeated function call?

Is it possible to do this

int foo(){
  static int i=0;
  ret = i++;
  return ret;
}
const std::array<int,3> arr = {{foo(),foo(),foo()}};

      

in a function (template?) or in a way that specifies "calling foo to initialize each element"? ie

const std::array<int,3> arr = fill_with_foo<3,foo>();

      

For context, arr is a buffer from the queue from which N elements will be read (known at compile time). I am currently using code generation to create a long form and I have a function that just selects a normal array, fills it with a for loop and returns the array, but I am wondering if it is possible to have a const buffer array.

// Edit: unlike the linked "duplicate" I need

int foo();

      

be non-deterministic at compile time, i.e. I think constexpr is out of the question (as I said, it needs to be read from a queue that gets populated at runtime). I'm mainly interested in getting rid of the useless copies.

+3


source to share


2 answers


Since C ++ 14 can use std :: index_sequnce (or implement it manually for older versions):

namespace detail
{

template<typename T, std::size_t N, typename F, std::size_t... I>
constexpr std::array<T, N> construct(F&& func, std::index_sequence<I...>)
{
    return { { (static_cast<void>(I), func())... } };
}

template<typename T, std::size_t N, typename F>
constexpr std::array<T, N> construct(F&& func)
{
    return construct<T, N>(std::forward<F>(func), std::make_index_sequence<N>());
}

}

      

Then you can apply it like this:

const auto array = detail::construct<T, 3>(foo);

      



FULL CODE

Also note that constexpr

it allows you to build std::array

even at compile time.

EXAMPLE

+4


source


Consider that the function returns std::array

. NRVO on most compilers will return a copy.

#include <array>
#include <iostream>

template <typename T, std::size_t N, typename F>
std::array<T, N> fill_array(F const &fn)
{
    std::array<T, N> arr;

    for (auto i = std::begin(arr); i != std::end(arr); ++i) {
        *i = fn();
    }

    return arr;
}

int foo(){
  static int i=0;
  return i++;
}

int main() {
    auto const arr = fill_array<int, 3>(foo);
    for (auto const &i : arr) {
        std::cout << i << '\n';
    }
    return 0;
}

      



Demo

+3


source







All Articles