Getting value from a tuple by type (instead of index)
As in C ++ 11, there is no STL way to get the first element of a tuple of type T
In C ++ 14, there should be a way to use the new std::get overload to do what you want. The ISO paper is here N3404 and here N3670 .
You can do this in C ++ 11 with the following:
#include<tuple> #include<type_traits> #include<string> #include<iostream> template<int Index, class Search, class First, class... Types> struct get_internal { typedef typename get_internal<Index + 1, Search, Types...>::type type; static constexpr int index = Index; }; template<int Index, class Search, class... Types> struct get_internal<Index, Search, Search, Types...> { typedef get_internal type; static constexpr int index = Index; }; template<class T, class... Types> T get(std::tuple<Types...> tuple) { return std::get<get_internal<0,T,Types...>::type::index>(tuple); }
I have it posted on Ideone here , but here is my test function for posterity
int main() { std::tuple<int, double, std::string> test{1, 1.7, "test"}; std::cout<<"get<0> == get<int> :"<< (std::get<0>(test) == get<int>(test))<< "\n"; std::cout<<"get<1> == get<double> :"<<(std::get<1>(test) == get<double>(test))<< "\n"; std::cout<<"get<2> == get<std::string> :"<<(std::get<2>(test) == get<std::string>(test))<< "\n"; }
Based on @Yakk's idea of ββextending this to support multiple instances of a type, as well as a predicate for testing in a tuple, he provided the code below (also posted on Ideone here )
Be warned: in C ++ 14, the new overload of std::get does not allow multiple instances of the same type in a tuple. Instead, a compilation error occurs. In addition, C ++ 14 will also not support predicates.
//Include same headers as before template<bool b, typename T=void> using EnableIf = typename std::enable_if<b,T>::type; template<int Index, template<typename T>class Search, int Which, typename, class First, class... Types> struct get_internal: get_internal<Index + 1, Search, Which, void, Types...> {}; template<int Index, template<typename T>class Search, int Which, class First, class... Types> struct get_internal<Index, Search, Which, EnableIf<!Search<First>::value>, First, Types...>: get_internal<Index + 1, Search, Which, void, Types...> {}; template<int Index, template<typename T>class Search, int Which, class First, class... Types> struct get_internal<Index, Search, Which, EnableIf<Search<First>::value>, First, Types...>: get_internal<Index + 1, Search, Which-1, void, Types...> {}; template<int Index, template<typename T>class Search, class First, class... Types> struct get_internal<Index, Search, 0, EnableIf<Search<First>::value>, First, Types...>: std::integral_constant<int, Index> {}; template<template<typename>class Test, int Which=0, class... Types> auto get(std::tuple<Types...>& tuple)-> decltype(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple)) { return std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple); } template<template<typename>class Test, int Which=0, class... Types> auto get(std::tuple<Types...> const& tuple)-> decltype(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple)) { return std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple); } template<template<typename>class Test, int Which=0, class... Types> auto get(std::tuple<Types...>&& tuple)-> decltype(std::move(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple))) { return std::move(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple)); } template<typename T> struct is_type { template<typename U> using test = std::is_same<T,U>; }; template<class T, int Which=0, class... Types> T& get(std::tuple<Types...>& tuple) { return get<is_type<T>::template test,Which>(tuple); } template<class T, int Which=0, class... Types> T const& get(std::tuple<Types...> const& tuple) { return get<is_type<T>::template test,Which>(tuple); } template<class T, int Which=0, class... Types> T&& get(std::tuple<Types...>&& tuple) { return std::move(get<is_type<T>::template test,Which>(tuple)); }
Getting the type of the nth element in a tuple
There is a way to get the type of the nth element. std::tuple_element<n, decltype(tuple)>::type (thanks @syam) is the type of the nth element of the tuple.