Во-первых, существует несколько решений:
Solution 1
auto indices = hana::to<hana::tuple_tag>(hana::range_c<std::size_t, 0, sizeof...(T)>);
auto types = hana::make_tuple(std::forward<T>(args)...);
hana::for_each(hana::zip(indices, types), hana::fuse([](auto i, auto&& x) {
// ...
}));
Раствор 2
auto indices = hana::range_c<std::size_t, 0, sizeof...(T)>;
auto types = hana::make_tuple(std::forward<T>(args)...);
hana::for_each(indices, [&](auto i) {
auto& x = types[i];
// ...
});
Раствор 3
auto types = hana::make_tuple(std::forward<T>(args)...);
hana::size_c<sizeof...(T)>.times.with_index([&](auto i) {
auto& x = types[i];
// ...
});
Решение (1) имеет тот недостаток, что делает копию каждого args
, потому что zip
возвращает последовательность последовательностей, и все это Hana по значению. Поскольку это, вероятно, не то, что вы хотите, вы должны выбрать то, что вы предпочитаете между решениями (2) и (3), которые действительно эквивалентны.
Теперь, почему range
s не моделирует концепцию Sequence
, потому что это не имеет смысла. Концепция Sequence
требует, чтобы мы могли создать произвольное Sequence
с помощью функции hana::make
. Следовательно, для любого Sequence
тега S
, hana::make<S>(...)
необходимо создать Sequence
тега S
, который содержит ...
. Однако a range
должен содержать смежный integral_constant
s в некоторый интервал. Следовательно, если range
был равен Sequence
, hana::make<hana::range_tag>(...)
должен содержать все, что ...
, что разрушает инвариант range
, если ...
не смежны integral_constant
с. Рассмотрим, например
hana::make<hana::range_tag>(hana::int_c<8>, hana::int_c<3>,
hana::int_c<5>, hana::int_c<10>)
Это должно быть range
, содержащий integral_constant
s 8,3,5,10
, который не имеет смысла. Другим аналогичным примером, показывающим, почему range
не может быть Sequence
, является алгоритм permutations
. Алгоритм permutations
принимает Sequence
и возвращает Sequence
из Sequence
s, содержащий все перестановки. Ясно, что поскольку range
может содержать только integral_constant
с, нет смысла пытаться создать range
range
с. Таких примеров достаточно.
Иными словами, range
s являются слишком специализированными, чтобы моделировать концепцию Sequence
. Потенциал такой специализированной структуры заключается в том, что она очень эффективна для компиляции. Недостатком является то, что это не универсальный контейнер, и некоторые операции на нем не могут быть выполнены (например, zip
). Тем не менее, вы можете полностью взять range
и преобразовать его в полномасштабную последовательность, если знаете, что такое компромисс.