简体   繁体   中英

How to fill const std::array<size_t, N> with values based on function

How to create const std::array containing following values f(0), f(1), ..., f(N-1) where f is any function: static constexpr size_t f(int index)? When I know exactly NI can obviously write

const std::array<size_t, 5> a = {f(0), f(1), f(2), f(3), f(4)}

A general technique for creating constants that require arbitrarily complex initialization is to simply write a function that returns the value you want, and then call that in the constant's initializer. For example:

template <typename T, size_t N>
array<T, N> init_from_f() {
    array<T, N> a;
    for (size_t i = 0; i < N; ++i)
        a[i] = f(i);
    return a;
}

const auto const_array = init_from_f<sometype, 42>();

It might need polishing but that's what I thought:

template <std::size_t... ns, typename Fn>
auto fill_helper(std::integer_sequence<std::size_t, ns...>, Fn&& fn) -> std::array<decltype(fn(std::size_t())), sizeof...(ns)>  {
    return {{fn(ns)...}};
} 

template <std::size_t N, typename Fn>
auto fill(Fn&& fn) {
    using seq = std::make_integer_sequence<std::size_t, N>;
    return fill_helper(seq(), std::forward<Fn>(fn));    
}

int main() {

    auto plus5 = [](std::size_t index) {
        return index + 5;
    };

    auto const as = fill<5>(plus5);
    for (auto&& a: as)
        std::cout << a;

}

The advantage is that you are initializing the array with the proper values, rather than first initializing and then assigning.

You could also do something like this if you want to const-initialize it without creating an external function:

void SomeFunction() {

    const auto my_array = [](){
        auto a = array<SomeType, N>();
        for (size_t i = 0; i < a.size(); ++i)
            a[i] = f(i);
        return a;
    }(); // <-- Note that the lambda executes right away

    DoSomeStuff(my_array);
}

Use a lambda and std::generate :

#include<array>
#include<algorithm> // generate
#include<cassert>
#include<iostream>

int f(int i){return i*i;}

int main(){
    const std::array<int, 5> a = []{
        std::array<int, 5> a;
        int n = 0;
        std::generate(a.begin(), a.end(), [&n]{ return f(n++); });
        return a;
    }();
    assert( a[4] == 16 );
}

http://coliru.stacked-crooked.com/a/60e2ec92e648519d

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM