#include <string>
#include <utility>
#include <vector>
#include <boost/hana.hpp>
namespace hana = boost::hana;
template <typename ...T>
void indexed_T_work(T&& ...args)
{
auto indices = 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)
, [](auto&& pair_) { /* Do index-dependent work with each `T` */ }
);
}
int main()
{
indexed_T_work(5, 13, std::vector<std::string>{}, 32.f, 42, "foo");
}
Я хотел бы использовать hana::zip
на hana::tuple
а также hana::range_c
, но hana::range_c
не считается Последовательность, что является требованием для hana::zip
, В чем причина этого решения? Как я могу (идиоматически) достичь своей цели, уважая это решение?
Во-первых, есть несколько решений:
Решение 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
возвращает последовательность последовательностей, и все в хане по значению. Так как это, вероятно, не то, что вы хотите, вы должны выбрать то, что вы предпочитаете между решениями (2) а также (3), которые действительно эквивалентны.
Теперь причина, почему range
не моделировать Sequence
Концепция заключается в том, что это не имеет смысла. Sequence
Концепция требует, чтобы мы были в состоянии создать произвольную Sequence
с использованием hana::make
функция. Следовательно, для любого Sequence
тег S
, hana::make<S>(...)
должен создать Sequence
тега S
который содержит ...
, Тем не менее, range
должен содержать смежные integral_constant
в некотором интервале. Следовательно, если range
был Sequence
, hana::make<hana::range_tag>(...)
должен содержать что угодно ...
есть, который нарушает инвариант range
если ...
не смежны integral_constant
s. Рассмотрим для примера
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
ы, содержащие все перестановки. Понятно, что с range
может только держать integral_constant
с, нет смысла пытаться создать range
из range
s. Подобных примеров предостаточно.
Другими словами, range
они слишком специализированы, чтобы моделировать Sequence
концепция. Преимущество такой специализированной структуры в том, что она очень эффективна во время компиляции. Недостатком является то, что это не контейнер общего назначения, и с ним нельзя выполнить некоторые операции (например, zip
). Тем не менее, вы можете полностью взять range
и преобразовать его в полноценную последовательность, если вы знаете, что такое компромисс.
Других решений пока нет …