Skip to content

Instantly share code, notes, and snippets.

@dolinenkov
Created July 29, 2020 14:46
Show Gist options
  • Save dolinenkov/44972adb7d6a66e9815e1a9d75607394 to your computer and use it in GitHub Desktop.
Save dolinenkov/44972adb7d6a66e9815e1a9d75607394 to your computer and use it in GitHub Desktop.
C++ templates - get element by tuple index and type
#include <cstddef>
#include <type_traits>
#include <tuple>
#include <iostream>
namespace tuple_utils {
template<typename ElementType, const size_t TypeOrdinal, size_t MatchCounter, size_t OverallCounter, typename Tuple>
ElementType & get_by_index_and_type(Tuple && tuple) {
using T = std::remove_reference_t<Tuple>;
constexpr bool is_of_required_type = std::is_same_v<ElementType, std::tuple_element_t<OverallCounter, T>>;
static_assert(OverallCounter < std::tuple_size_v<T>, "Tuple type index out of bounds");
if constexpr (is_of_required_type) {
if constexpr (TypeOrdinal == MatchCounter) {
return std::get<OverallCounter>(std::forward<Tuple>(tuple));
}
else {
return get_by_index_and_type<ElementType, TypeOrdinal, MatchCounter + 1, OverallCounter + 1, Tuple>(std::forward<Tuple>(tuple));
}
}
else {
return get_by_index_and_type<ElementType, TypeOrdinal, MatchCounter, OverallCounter + 1, Tuple>(std::forward<Tuple>(tuple));
}
}
}
template<typename Type, size_t Index, typename Tuple>
Type & tuple_get(Tuple && tuple) {
return tuple_utils::get_by_index_and_type<Type, Index, 0, 0, Tuple>(std::forward<Tuple>(tuple));
}
int main(int, char*[]) {
auto tuple = std::make_tuple(int(0), double(0.0), int(1));
std::cout << tuple_get<int, 0>(tuple) << std::endl;
std::cout << tuple_get<int, 1>(tuple) << std::endl;
std::cout << tuple_get<double, 0>(tuple) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment