24

I want to make a template where I can input an index and it will give me the type at that index. I know I can do this with decltype(std::get<N>(tup)) but I would like to implement this myself. For example, I would like to do this,

typename get<N, std::tuple<int, bool, std::string>>::type;

...and it will give me the type at position N - 1 (because arrays indexed starting from 0). How can I do this? Thanks.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
user2030677
  • 3,448
  • 4
  • 23
  • 36

2 Answers2

26

That trait already exists, and it is called std::tuple_element.

Here is a live example that demonstrates its usage.

#include <tuple>
#include <type_traits>

int main()
{
    using my_tuple = std::tuple<int, bool, char>;
    static_assert(std::is_same<std::tuple_element<0, my_tuple>::type, int>::value, "!");
    static_assert(std::is_same<std::tuple_element<1, my_tuple>::type, bool>::value, "!");
    static_assert(std::is_same<std::tuple_element<2, my_tuple>::type, char>::value, "!");
}
Catskul
  • 17,916
  • 15
  • 84
  • 113
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • 1
    But I said I wanted to implement this myself. :) – user2030677 Jun 04 '13 at 23:04
  • Given that *"I know I can do this but I would like to implement this myself."*, this is not an answer but a comment (though a useful one, since the OP doesn't seem to know about `std::tuple_element`). – Christian Rau Jun 05 '13 at 07:28
  • @user2030677: I'm sorry, I should have read the question's text better - I somehow skipped that part :) – Andy Prowl Jun 05 '13 at 08:11
  • @ChristianRau: Yes, I did not realize that when I wrote the answer (and I re-read the question a couple of times, my brain just skipped that part) – Andy Prowl Jun 05 '13 at 08:12
  • 1
    Might be the case that this doesn't fulfill all the constraints of the asker's question, but it's great for people coming in from a google search who don't care about implementing it themselves :) – chili May 06 '22 at 23:44
  • C++14 also provides a `std::tuple_element_t<>` alias, which is short for `std::tuple_element<>::type`. – pcfist Feb 21 '23 at 11:14
23

You can use a class template and partial specializations to do what you want. (Note that std::tuple_element does almost the same like the other answer says):

#include <tuple>
#include <type_traits>

template <int N, typename... Ts>
struct get;

template <int N, typename T, typename... Ts>
struct get<N, std::tuple<T, Ts...>>
{
    using type = typename get<N - 1, std::tuple<Ts...>>::type;
};

template <typename T, typename... Ts>
struct get<0, std::tuple<T, Ts...>>
{
    using type = T;
};

int main()
{
    using var = std::tuple<int, bool, std::string>;
    using type = get<2, var>::type;

    static_assert(std::is_same<type, std::string>::value, ""); // works
}
David G
  • 94,763
  • 41
  • 167
  • 253