// needed for is_same
#include <type_traits>
#include <tuple>
#include <iostream>

using namespace std;

// this should be an inner and private metafunction of exists_type
// I put here for clarity
template<typename T, typename Tuple, const int index>
struct exists_type_index
{
    static const bool value =
        is_same < T, typename tuple_element<index, Tuple>::type >::value ||
                  exists_type_index<T, Tuple, index-1>::value;
};

// stop the recursion when reach the first element
template<typename T, typename Tuple>
struct exists_type_index<T, Tuple, 0>
{
    static const bool value = is_same < T, typename tuple_element<0, Tuple>::type >::value;
};

// exists_type metafunction (clients call this)
template<typename T, typename Tuple>
struct exists_type
{
    static const bool value = exists_type_index<T, Tuple, tuple_size<Tuple>::value-1>::value;
};

////////////////////////// Executor

template<bool b>
struct Executor
{
 template<typename T>
 static void execute(T&&)
 {
    cout << "General case" << endl;
 }
};

template<>
struct Executor <true>
{
 template<typename T>
 static void execute(T&&)
 {
    cout << "Specific case" << endl;
 }
};

// clients call this
template<typename Tuple>
struct MultiTypeDispatcher
{
 template<typename T>
 void function( T&& t )
 {
      Executor<exists_type<T, Tuple>::value>::execute(forward<T>(t));
 }
};


int main()
{
    MultiTypeDispatcher< tuple<int, float, string> > dispatcher;

    dispatcher.function(string("hello!")); // Specific case!
    dispatcher.function(1.0f); // Specific case!
    dispatcher.function(1.0); // General case!
    
    return 0;
}