Как создать пользовательскую целочисленную последовательность в C++

у меня есть такая функция:

template <typename ... Types>
void foo(const Types & ... values)
{
    // expected that 'values' is sequence like
    // '1, customvalue1, 2, customvalue2, 3,...'
}

и вторая функция:

template <typename ... Types>
void bar(const Types & ... values)
{
    // where 'values' are any variables
    // some magic here
    foo((int_seq<sizeof...(Types)>, values)...);
}

Я хотел бы передать любую последовательность переменных в бар, так что эта последовательность преобразуется в последовательность, как '1, value1, 2, value2, 3, value3'. Таким образом, каждое значение следует своему номеру в базовой последовательности. Но я не могу создать это 'волшебный код' для преобразования последовательности на этапе компиляции между этими двумя состояниями.

2 ответов


не очень элегантный, но, используя кортежи,std::tie, etc...

следующий пример должен работать с C++11

--- редактировать ---

Modified and unified (C++11 без элементов C++14) мой первый пример.

Не нужно std::index_sequence (тривиальное struct indSeq можно использовать вместо) или std::make_index_sequence (последовательность индексов может быть построена шаг за шагом с помощью sizeof...(I)); не нужно


вот решение C++14, но все необходимые части библиотеки также могут быть написаны на C++11.

#include <iostream>
#include <tuple>
#include <utility>

template <typename ... Types>
void foo(const Types & ... values)
{
    using swallow = bool[];
    (void)swallow{ (std::cout << values << std::endl,false)... };
}

template <std::size_t N, bool = (N%2==0)>
struct pick {
    template<typename... Types>
    static std::size_t get(const std::tuple<Types...>&) { return N/2; }
};

template <std::size_t N>
struct pick<N,false> {
    template<typename... Types>
    static auto get(const std::tuple<Types...>& t) { return std::get<N/2>(t); }
};

template <std::size_t... Indices, typename ... Types>
void bar2(const std::index_sequence<Indices...>, const Types & ... values)
{
    auto x = std::tie(values...);
    foo(pick<Indices>::get(x)...);
}

template <typename ... Types>
void bar(const Types & ... values)
{
    bar2(std::index_sequence_for<Types...,Types...>(), values...);
}

int main()
{
    bar( "Hallo", 42, 1.23 );
}

видео

в настоящее время он основан на нуле, но +1 в нужном месте это легко исправить. Кроме того, он создает промежуточное std::tuple со ссылками на значения, если производительность является проблемой, могут существовать лучшие варианты, но так как вы не использовали std::forward Я подумал, что небольшое влияние на производительность может быть приемлемый для вас.