std::visit for std::tuple

mrgordonfreman
mrgordonfreman

Судя по запросам в гугле, проблема обхода std::tuple многих беспокоит.

Для себя я решил её так

template<typename Visitor, typename... Args>
void visit(std::tuple<Args...> const& t, Visitor&& vis)
{
    (..., vis(std::get<Args>(t)));
}

template<typename Visitor, typename... Args>
void visit(std::tuple<Args...>& t, Visitor&& vis)
{
    (..., vis(std::get<Args>(t)));
}

auto t = std::make_tuple(100, "500", '!');
visit(t, [](auto&& x) {
    std::cout << x;
});

Хочется иметь такие функции в стандартной библиотеке и не создавать велосипедов

7
рейтинг
3 комментария
mrgordonfreman
Приведенный вариант не работает, если в tuple будет несколько одинаковых типов. Лучше делать через индексы

template<typename T, typename V, size_t... I>
void visit_impl(T&& t, V&& v, std::index_sequence<I...>)
{
(..., v(std::get<I>(t)));
}

template<typename T, typename V>
void visit(T&& t, V&& v)
{
visit_impl(std::forward<T>(t), std::forward<V>(v),
std::make_index_sequence<std::tuple_size<
typename std::decay<T>::type>::value>());
}
mrgordonfreman
Сергей Вахреев
А почему бы просто не использовать std::apply и folding expressions, которые есть в 17 стандарте?
std::apply([] (auto&&... value) { ((std::cout << value), ...); },
std::make_tuple(100, "500", '!'));
Сергей Вахреев
yndx-antoshkka
На заседании в Коне 2017 решили продумывать идею с циклами по гетерогенным контейнерам. Что-то наподобие:

for constexpr(auto v: std::make_tuple(100, "500", '!')) {
std::cout << v;
}


Бонусом получим итерацию по variadic template:

template <class... Args>
void foo(const Args&... args) {
for constexpr(auto v: args...) {
std::cout << v;
}
}

Так что торопиться с написанием proposal для std::visit пока не стоит.
yndx-antoshkka
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).