Почему `boost :: hana :: range_c` не является последовательностью?

#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, В чем причина этого решения? Как я могу (идиоматически) достичь своей цели, уважая это решение?

2

Решение

Во-первых, есть несколько решений:

Решение 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_constants. Рассмотрим для примера

hana::make<hana::range_tag>(hana::int_c<8>, hana::int_c<3>,
hana::int_c<5>, hana::int_c<10>)

Это должно быть range содержащий integral_constants 8,3,5,10, что не имеет смысла. Еще один похожий пример, показывающий, почему range не может быть Sequence это permutations алгоритм. permutations алгоритм принимает Sequence и возвращает Sequence из Sequenceы, содержащие все перестановки. Понятно, что с range может только держать integral_constantс, нет смысла пытаться создать range из ranges. Подобных примеров предостаточно.

Другими словами, rangeони слишком специализированы, чтобы моделировать Sequence концепция. Преимущество такой специализированной структуры в том, что она очень эффективна во время компиляции. Недостатком является то, что это не контейнер общего назначения, и с ним нельзя выполнить некоторые операции (например, zip). Тем не менее, вы можете полностью взять range и преобразовать его в полноценную последовательность, если вы знаете, что такое компромисс.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]