Removing the first type of a std::tuple

You can use a simple type function based on partial specialization of a class template:

#include <type_traits>
#include <tuple>

using namespace std;

template<typename T>
struct remove_first_type
{
};

template<typename T, typename... Ts>
struct remove_first_type<tuple<T, Ts...>>
{
    typedef tuple<Ts...> type;
};

int main()
{
    typedef tuple<int, bool, double> my_tuple;
    typedef remove_first_type<my_tuple>::type my_tuple_wo_first_type;

    static_assert(
        is_same<my_tuple_wo_first_type, tuple<bool, double>>::value, 
        "Error!"
        );
}

Also, this solution can be easily generalized to remove the i-th type of a tuple:

#include <type_traits>
#include <tuple>

using namespace std;

template<size_t I, typename T>
struct remove_ith_type
{
};

template<typename T, typename... Ts>
struct remove_ith_type<0, tuple<T, Ts...>>
{
    typedef tuple<Ts...> type;
};

template<size_t I, typename T, typename... Ts>
struct remove_ith_type<I, tuple<T, Ts...>>
{
    typedef decltype(
        tuple_cat(
            declval<tuple<T>>(),
            declval<typename remove_ith_type<I - 1, tuple<Ts...>>::type>()
            )
        ) type;
};

int main()
{
    typedef tuple<int, bool, double> my_tuple;
    typedef remove_ith_type<1, my_tuple>::type my_tuple_wo_2nd_type;

    static_assert(
        is_same<my_tuple_wo_2nd_type, tuple<int, double>>::value, 
        "Error!"
        );
}

I wrote a proposal which was accepted into the C++14 standard making it quite easy to do for any "tuple-like" type, i.e. one that supports the tuple_size and tuple_element API:

template<typename T, typename Seq>
    struct tuple_cdr_impl;

template<typename T, std::size_t I0, std::size_t... I>
    struct tuple_cdr_impl<T, std::index_sequence<I0, I...>>
    {
        using type = std::tuple<typename std::tuple_element<I, T>::type...>;
    };

template<typename T>
    struct tuple_cdr
    : tuple_cdr_impl<T, std::make_index_sequence<std::tuple_size<T>::value>>
    { };

And you can transform a tuple object into the new type with only a couple of functions:

template<typename T, std::size_t I0, std::size_t... I>
typename tuple_cdr<typename std::remove_reference<T>::type>::type
cdr_impl(T&& t, std::index_sequence<I0, I...>)
{
    return std::make_tuple(std::get<I>(t)...);
}

template<typename T>
typename tuple_cdr<typename std::remove_reference<T>::type>::type
cdr(T&& t)
{
    return cdr_impl(std::forward<T>(t),
                    std::make_index_sequence<std::tuple_size<T>::value>{});
}

This creates an integer sequence [0,1,2,...,N) where N is tuple_size<T>::value, then creates a new tuple with make_tuple(get<I>(t)...) for I in [1,2,...,N)

Testing it:

using tuple1 = std::tuple<int, short, double>;
using tuple2 = std::tuple<short, double>;
using transformed = decltype(cdr(std::declval<tuple1>()));
static_assert(std::is_same<transformed, tuple2>::value, "");
static_assert(std::is_same<tuple_cdr<tuple1>::type, tuple2>::value, "");


#include <iostream>

int main()
{
    auto t = cdr(std::make_tuple(nullptr, "hello", "world"));
    std::cout << std::get<0>(t) << ", " << std::get<1>(t) << '\n';
}

My reference implementation for the proposal is at https://gitlab.com/redistd/integer_seq/blob/master/integer_seq.h


I came up with a solution very similar to that proposed by @Andy, but that tries to be a bit more generic by working directly on the parameter pack (using a dummy wrapper) rather than on std::tuple. This way, the operation can be applied to other variadic templates as well, not only to tuples:

#include <type_traits>
#include <tuple>

template <typename... Args> struct pack {};

template <template <typename...> class T, typename Pack>
struct unpack;

template <template <typename...> class T, typename... Args>
struct unpack<T, pack<Args...>>
{
    typedef T<Args...> type;
};

template <typename T, typename Pack>
struct prepend;

template <typename T, typename... Args>
struct prepend<T, pack<Args...>>
{
    typedef pack<T, Args...> type;
};

template <std::size_t N, typename... Args>
struct remove_nth_type;

template <std::size_t N, typename T, typename... Ts>
struct remove_nth_type<N, T, Ts...>
    : prepend<T, typename remove_nth_type<N-1, Ts...>::type>
{};

template <typename T, typename... Ts>
struct remove_nth_type<0, T, Ts...>
{
    typedef pack<Ts...> type;
};

template <typename T, int N>
struct remove_nth;

template <template <typename...> class T, int N, typename... Args>
struct remove_nth<T<Args...>, N>
{
    typedef typename
        unpack<
            T, typename 
            remove_nth_type<N, Args...>::type
        >::type type;
};

template <typename... Args>
struct my_variadic_template
{
};

int main()
{
    typedef std::tuple<int, bool, double> my_tuple;
    typedef remove_nth<my_tuple, 1>::type my_tuple_wo_2nd_type;

    static_assert(
        is_same<my_tuple_wo_2nd_type, tuple<int, double>>::value, 
        "Error!"
        );

    typedef my_variadic_template<int, double> vt;
    typedef remove_nth<vt, 0>::type vt_wo_1st_type;

    static_assert(
        is_same<vt_wo_1st_type, my_variadic_template<double>>::value, 
        "Error!"
        );
}

pack is an helper structure whose sole purpose is to store a template parameter pack. unpack can then be used to unpack the parameters into an arbitrary class template (thanks to @BenVoigt for this trick). prepend simply prepends a type to a pack.

remove_nth_type uses partial template specialization to remove the nth type from a parameter pack, storing the result into a pack. Finally, remove_nth takes a specialization of an arbitrary class template, remove the nth type from its template parameters, and return the new specialization.