Detect if a type is a std::tuple?

Sure, using is_specialization_of (link taken and fixed from here):

template<typename Type, bool IsTuple = is_specialization_of<Type, std::tuple>::value>
bool f(Type* x);

The question is, however, do you really want that? Normally, if you need to know if a type is a tuple, you need special handling for tuples, and that usually has to do with its template arguments. As such, you might want to stick to your overloaded version.

Edit: Since you mentioned you only need a small portion specialized, I recommend overloading but only for the small special part:

template<class T>
bool f(T* x){
  // common parts...
  f_special_part(x);
  // common parts...
}

with

template<class T>
void f_special_part(T* x){ /* general case */ }

template<class... Args>
void f_special_part(std::tuple<Args...>* x){ /* special tuple case */ }

With C++17, here is a fairly simple solution using if constexpr

template <typename> struct is_tuple: std::false_type {};

template <typename ...T> struct is_tuple<std::tuple<T...>>: std::true_type {};

Then you can do something like:

template<typename Type> bool f(Type* x) {
    if constexpr (is_tuple<Type>::value) {
        std::cout << "A tuple!!\n";
        return true;
    }

    std::cout << "Not a tuple\n";
    return false;
}

A test to ensure it worked:

f(&some_tuple);
f(&some_object);

Output:

A tuple!!
Not a tuple


Solution taken in part from an answer found here: How to know if a type is a specialization of std::vector?


You could just have your functions defer to another function:

template<typename Type,bool IsTuple> bool f(Type *x);

template<typename Type> 
inline bool f(Type* x) { return f<Type,false>(x); }

template<typename... List> 
inline bool f(std::tuple<List...>* x) { return f<std::tuple<List...>,true>(x); }