Извлечение типов элементов из пакета параметров

Я хотел бы определить функцию, которая принимает произвольное количество контейнеров и это число минус один аргумент с соответствующими значениями value_types всех, кроме последнего контейнера.

Я могу легко извлечь value_type из последнего контейнера и использовать его в качестве возвращаемого типа, однако я не знаю, как определить типы для аргументов. Я мог бы представить, что сворачивание std::integer_sequence внутри std::tuple_element_t может быть способом сделать это, но мне не удалось заставить его работать.

// example: 1D interpolator
template<typename... ContainerTypes>
typename std::tuple_element_t<
    sizeof...(ContainerTypes) - 1,
    std::tuple<ContainerTypes...>>::value_type
interpolate(const ContainerTypes& ... /*, ??? */)
{
    // (...)
    return {};
}

// intended use
std::array<int, 2> x{0, 2};
std::array<double, 2> y{0, 2};
int x_query{1};

double y_interpolated{interpolate(x, y)}; // compiles
//double y_interpolated{interpolate(x, y, x_query)}; // this is what I want

1 ответ

Решение

Как я понимаю, вы хотите преобразовать перегрузки:

template <typename C1, typename CLast>
typename CLast::value_type interpolate(const C1&,
                                       const CLast&,
                                       typename C1::value_type);

template <typename C1, typename C2, typename CLast>
typename CLast::value_type interpolate(const C1&, const C2&,
                                       const CLast&
                                       typename C1::value_type, typename C2::value_type);
// ...

в вариационный шаблон.

Было бы проще иметь промежуточную структуру:

template <typename T, typename ... Ts>
struct InterpolatorImpl
{
    const T& t;
    std::tuple<const Ts&...> ts;

    InterpolatorImpl(const T& t, const Ts&... ts) : t(t), ts(ts...) {}

    typename T::value_type operator()(typename Ts::value_type...) const {/*...*/};
};


template <std::size_t...Is, typename Tuple>
auto InterpolatorHelper(std::index_sequence<Is...>, const Tuple& tuple) {
    using LastType = tuple_element_t<sizeof...(Is), tuple>;
    return InterpolatorImpl<LastType,
                            std::decay_t<std::tuple_element_t<Is, tuple>>...>
        {
            std::get<sizeof...(Is)>(tuple),
            std::get<Is>(tuple)...
        };
}

template <typename ...Ts>
auto Interpolator(const Ts&... ts) {
    return InterpolatorHelper(std::make_index_sequence<sizeof...(Ts) - 1>(),
                              std::tie(ts...));
}

А потом, назовите это:

std::array<int, 2> x{0, 2};
std::array<double, 2> y{0, 2};
int x_query{1};

double y_interpolated{Interpolator(x, y)(x_query)};

Или измените свою подпись на

template <typename ... InputContainers, typename TargetContainer>
typename TargetContainer::value_type
interpolate(const std::tuple<InputContainers...>&,
            const TargetContainer&,
            const std::tuple<typename InputContainers::value_type...>&);
Другие вопросы по тегам