2016-05-07 3 views
2

При попытке ответить на this question, я нашел себя в необходимости создания кучи параметров для VARIADIC функции на лета, где:Функции для создания кортежа с учетом размером N и типа T

  • числа параметров не дано
  • типов все одинаковы, но неизвестно (даже если они должны быть конструктивна по умолчанию)

Во время исполнения стандартные контейнеры и для цикла можно использовать для этого.
Во всяком случае, я хотел бы сгенерировать набор параметров во время компиляции, чтобы иметь возможность пересылать их на переменную функцию.
Из-за этого, std::tuple казалось очевидным решением.

Здесь возник вопрос: с учетом размера N и конструктивного типа по умолчанию T во время компиляции, как я могу написать функцию для генерации кортежа заданного размера?

Я ищу что-то вроде этого:

auto tup = gen<MyType, N>(); 

На SO является notable example из основанных рекурсивного генератора, но я структуры борюсь с функцией на основе решения, и я не смог найти его в любом месте.

+1

Если типы все одинаковые, я бы использовал 'std :: array ' вместо кортежа. – davidhigh

+0

@ davihigh Конечно. Я закончил тем, что использовал кортеж, потому что это было действительно сложнее. Я сделал это, чтобы экспериментировать, больше ничего. Если бы я столкнулся с реальной проблемой, я бы тоже использовал «массив». – skypjack

ответ

3

Правильно написанная функция переадресации (а-ля std::apply) должны работать с std::array<T, N> и все остальное, что реализует интерфейс с std::tuple_size/std::get. Тем не менее,

template<size_t, class T> 
using T_ = T; 

template<class T, size_t... Is> 
auto gen(std::index_sequence<Is...>) { return std::tuple<T_<Is, T>...>{}; } 

template<class T, size_t N> 
auto gen() { return gen<T>(std::make_index_sequence<N>{}); } 
+0

Ты заставил меня плакать! :-) ... Но, по крайней мере, было забавно экспериментировать с шаблонами, чтобы сделать такую ​​легкую вещь таким сложным способом. – skypjack

0

Вот возможная реализация такой функции:

#include<utility> 
#include<tuple> 

template<typename T> 
constexpr auto 
params(std::index_sequence<0>) { 
    return std::tuple<T>{}; 
} 

template<typename T, std::size_t I, std::size_t... O> 
constexpr auto 
params(std::index_sequence<I, O...>) { 
    auto tup = std::tuple<T>{ T{} }; 
    auto seq = std::make_index_sequence<sizeof...(O)>{}; 
    return std::tuple_cat(tup, params<T>(seq)); 
} 

template<typename T, std::size_t N> 
constexpr auto 
gen(std::integral_constant<std::size_t, N>) { 
    return params<T>(std::make_index_sequence<N>{}); 
} 

int main() { 
    auto tup = gen<int>(std::integral_constant<std::size_t, 3>{}); 
    static_assert(std::tuple_size<decltype(tup)>::value == 3, "!"); 
} 

Для простоты я использовал int как тип.
С небольшим усилием можно использовать пользовательские типы, и ограничение их по умолчанию может быть ослаблено.

 Смежные вопросы

  • Нет связанных вопросов^_^