Jeff G
Jeff G

Reputation: 4677

C++ Initialize Member Array with Constructor Argument

I have a template class that contains a single member array of compile-time constant length. I want this array to be constant, but initializing it based on constructor-provided input is proving difficult:

struct Input {
    int value;
};

template<size_t Size>
struct Foo {
    int const myVals[Size];
    Foo(std::array<Input, Size> const &in)
        : myVals{ in[0].value, in[1].value, /* How many times? */ } {
    }
}

Since I don't know the size of the array, I don't know how many values with which to initialize myVals. The following code works, but I question whether it is the best approach:

template<size_t Size>
struct Foo {
    std::array<int, Size> const myVals;
    Foo(std::array<Input, Size> const &in)
        : myVals{ toIntArray(in) } {
    }
private:
    static std::array<int, Size> toIntArray(std::array<Input, Size> const &in) {
        std::array<int, Size> result;
        for (size_t i{ 0 }; i < Size; ++i) {
            result[i] = in[i].value;
        }
        return result;
    }
}

Is there a more succinct, or generally more accepted way to populate the values of a constant member array?

Upvotes: 4

Views: 514

Answers (1)

HTNW
HTNW

Reputation: 29193

You can use std::index_sequence to get the indices of the array as a non-type template parameter pack. Then you can use a parameter pack expansion.

template<size_t Size>
struct Foo {
    int const myVals[Size];
    Foo(std::array<Input, Size> const &in)
        : Foo(in, std::make_index_sequence<Size>()) { }
    private:
    template<size_t... Is>
    Foo(std::array<Input, Size> const &in, std::index_sequence<Is...>)
        : myVals{in[Is].value...} { }
}

Using a helper template with a size_t... Is pack and a std::index_sequence<Is...> argument is a common pattern for handling fixed-size indexable containers. The index_sequence doesn't actually do anything; it's just a proxy so that the Is template arguments can be deduced. E.g. if you check on Godbolt it appears to totally evaporate under -O1.

Upvotes: 2

Related Questions