Захотелось странного (ну, почти): заставить работать std::apply с обьектом std::integer_sequence. Ведь последний – вполне себе кортеж.
А целью было бы упрощение паттерна (хз как называется) с обходом кортежей (С++17*):
template <typename Function,
typename Tuple,
std::size_t... indexes>
void doFoonktion(Function f, Tuple t, std::index_sequence<indexes...>) {
(static_cast<void>(f(std::get<indexes>(t))), ...);
}
template <typename Function,
typename Tuple>
void doFunction(Function f, Tuple t) {
doFoonktion(f, t, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
}
До такого:
template <typename Function,
typename Tuple>
void doFunction(Function f, Tuple t) {
std::apply([](auto... index) {
(static_cast<void>(f(std::get<index>(t))), ...);
},
std::make_index_sequence<std::tuple_size_v<T>>{});
}
- да, я знаю, что в С++20 можно явно делать шаблонные лямбды и второй «внешней» функции уже не надо было бы.
Значит сделать tuple_size и tuple_element для integer_sequence очень даже просто:
template <auto v>
using constant = std::integral_constant<decltype(v), v>;
template <typename T, T... values>
tuple_size<integer_sequence<T, values...>> : constant<sizeof...(values)>
{};
template <size_t i, typename T, T... values>
tuple_element<i, integral_sequence<T, values...>> { using type = T; };
Докостыливаем std::get
:
template <std::size_t i, typename T, T first, T... rest>
T get(integer_sequence<T, first, rest...>) {
if constexpr (i == 0)
return first;
else
return get<i - 1>(integer_sequence<T, rest...>{});
}
template <std::size_t i, typename T>
T get(integer_sequence<T>) {
static_assert(i != i, "invalid index");
}
После такого финта ушами начинает работать structured binding:
auto [zero, one, two, three] = std::make_index_sequence<4>{};
Однако std::apply «не видит» нашего std::get, если заголовок <tuple>
был включен ДО нашего определения get. Наверное там нету ADL: https://wandbox.org/permlink/GRDV7VEvalUWATlM
Есть идеи как сделать такое красиво/правильно? Ну и еще было бы круто вообще заставить std::apply работать с пользовательскими типами. Пока что на ум приходит только написание собственную реализацию std::apply c шлюхами и ADL.