C ++ 17 Итерация по подмножеству пакета параметров - PullRequest
1 голос
/ 19 января 2020

У меня есть структура, получающая пакет параметров. Предположим, что пакет параметров никогда не будет иметь размер меньше 3. Кроме того, std::array, найденный в структуре, должен оцениваться во время компиляции. Я хочу заполнить массив с помощью пакета параметров, но я хочу пропустить первый и последний элемент.

Это мой код:

#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;
}

В идеале, я бы хотел используйте std::index_sequence с элементами из [1, sizeof_parameter_pack - 1] или [0, size_of_parameter_pack - 2] и выражением сгиба для заполнения массива. Тем не менее, я борюсь с созданием index_sequence. Я не хочу, чтобы структура получила другой параметр шаблона. Как мне этого добиться?

Ответы [ 2 ]

3 голосов
/ 19 января 2020

Возможное решение с 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]...} {}
};
1 голос
/ 19 января 2020

Я думаю, что самый простой способ - это сделать следующее:

#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;
}

Это можно оценить во время выполнения (если ваш St объект не constexpr), вы можете обойти это, объявление члена массива constexpr.

Кстати: вы уверены, что хотите инициализировать массив int32_t с uint32_t?

...