#include<tuple>
#include<type_traits>
#include<string>
#include<iostream>

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>
{
    typedef get_internal type;
};

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<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);
}

int main()
{
    std::tuple<int, double, std::string, int, long> test{1, 1.7, "test", 7, 3};
    std::cout<<"get<0> == get<int> :"<< (std::get<0>(test) == get<int>(test))<< "\n";
    std::cout<<"get<3> == get<int,1> :"<< (std::get<3>(test) == get<int,1>(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";
    std::cout<<"get<0> == get<std::is_integral> :"<< (std::get<0>(test) == get<std::is_integral>(test))<< "\n";
    std::cout<<"get<3> == get<std::is_integral,1> :"<< (std::get<3>(test) == get<std::is_integral,1>(test))<< "\n";
    std::cout<<"get<4> == get<std::is_integral,2> :"<< (std::get<4>(test) == get<std::is_integral,2>(test))<< "\n";
}