Reputation:
I have a struct receiving a parameter pack. Let's assume that the parameter pack will never have a size smaller than 3. Also, the std::array
found in the struct should be evaluated at compile-time. I want to fill the array using the parameter pack, but I want to skip the first and the last element.
This is my code:
#include <iostream>
#include <array>
#include <cstdint>
template<int32_t ...Ts>
struct St {
const std::array<int32_t, sizeof...(Ts)-2U> arr{};
};
int main() {
constexpr St<7, 2, 1, 5, 6> s;
std::cout << s.arr[2] << std::endl;
return 0;
}
Ideally, I'd like to use a std::index_sequence
with elements from [1, sizeof_parameter_pack - 1] or [0, size_of_parameter_pack - 2] and a fold expression to fill the array. However, I'm struggling with creating the index_sequence. I don't want the struct to receive another template parameter. How can I achieve this?
Upvotes: 1
Views: 220
Reputation: 26342
Possible solution with std::index_sequence
:
template<int32_t... Ts>
struct St {
static constexpr auto Size = sizeof...(Ts) - 2;
const std::array<int32_t, Size> arr;
constexpr St() : St(std::array{Ts...}, std::make_index_sequence<Size>{}) {}
private:
template<class Arr, std::size_t... I>
constexpr St(Arr init, std::index_sequence<is...>) : arr{init[I + 1]...} {}
};
Upvotes: 2
Reputation: 5095
I think the easiest way is doing the following:
#include <iostream>
#include <array>
#include <cstdint>
template<uint32_t... Ts>
constexpr std::array<int32_t, sizeof...(Ts)-1> create_arr() {
const std::array<int32_t, sizeof...(Ts)> tmp{Ts...};
std::array<int32_t, sizeof...(Ts)-1> ret{};
// With C++20, this is a call to std::copy
for(auto i = 0ul; i != tmp.size()-1; ++i) {
ret[i] = tmp[i];
}
return ret;
}
template<uint32_t first, uint32_t ...Ts>
struct St {
const std::array<int32_t, sizeof...(Ts)-1> arr = create_arr<Ts...>();
};
int main() {
constexpr St<7U, 2U, 1U, 5U, 6U> s;
std::cout << s.arr[2] << std::endl;
return 0;
}
This can be evaluated at run-time (if your St
object is not constexpr
), you can get around that by declaring the array-member constexpr
.
Btw: Are you sure, that you want to initialize the int32_t
array from uint32_t
?
Upvotes: 0