Skip to content

Instantly share code, notes, and snippets.

@denniskb
Created July 25, 2023 08:18
Show Gist options
  • Save denniskb/2104d0d174c42b56e2167451fe1224cd to your computer and use it in GitHub Desktop.
Save denniskb/2104d0d174c42b56e2167451fe1224cd to your computer and use it in GitHub Desktop.
Looping over/dynamic indexing of std::tuple in C++17
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
template <int I>
struct constexpr_int{
constexpr operator int() const { return I; }
constexpr constexpr_int<I+1> operator++() const { return {}; }
};
// f: void(? tuple_element, constexpr_int index)
template <class T, class F>
void for_each_i(T&& t, F&& f) {
auto loop = [&](auto& self, auto i) {
f(std::get<i>(t), i);
if constexpr (i + 1 < std::tuple_size_v<std::decay_t<T>>)
self(self, ++i);
};
if constexpr (std::tuple_size_v<std::decay_t<T>> > 0)
loop(loop, constexpr_int<0>{});
}
// f: void(? tuple_element)
template <class T, class F>
void for_each(T&& t, F&& f) {
for_each_i(std::forward<T>(t), [&](auto&& elem, auto /*index*/){
f(std::forward<decltype(elem)>(elem));
});
}
// f: void (? tuple_element)
template <class T, class F>
void find(T&& tuple, int index, F&& f) {
for_each_i(std::forward<T>(tuple), [&](auto&& elem, auto i){
if (i == index) f(std::forward<decltype(elem)>(elem));
});
}
int main(int argc, char** argv) {
auto t = std::make_tuple("Hello", 3.14f, 42);
for_each(t, [](const auto& x){
std::cout << x << ' ';
});
std::cout << "\n\n";
for_each_i(t, [](const auto& x, auto i){
std::cout << i << ':' << x << '\n';
});
std::cout << '\n';
find(t, argc, [](const auto& x){
std::cout << x;
});
return 0;
}
// Prints:
// Hello 3.14 42
//
// 0:Hello
// 1:3.14
// 2:42
//
// 3.14
//
// try it: https://godbolt.org/z/ns6KqKGq3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment