Typelist with extractor
Naming

Templates depend on a consistent naming scheme for static polymorphism.

We can observe such consistent naming throughout the type traits offered by the standard library (from std::aligned_storage to std::add_pointer); the two most common names being:


A type alias member when the type trait produces a type result.
A value static data member to represent constexpr values.


This means that naming your extracted type alias as result is non-standard and breaks with any templates that assume the same naming convention from the standard library.

What is a type list?

There doesn't seem to be a specific purpose for having a type list that is defined in terms of a head and tail when variadic templates can easily represent what a type list is. Thus, we can simply define a type list as:

template &lt;class... Types&gt;
class type_list {};


What is extracting from a type list?

We can define a more general extraction template to extract from a variadic template.

template &lt;std::size_t idx, class... Types&gt;
class extract
{
    static_assert( idx &lt; sizeof...( Types ), "index out of bounds" );

    template &lt;std::size_t i, std::size_t n, class... Rest&gt;
    struct extract_impl;

    template &lt;std::size_t i, std::size_t n, class T, class... Rest&gt;
    struct extract_impl&lt;i, n, T, Rest...&gt;
    {
        using type = typename extract_impl&lt;i + 1, n, Rest...&gt;::type;
    };

    template &lt;std::size_t n, class T, class... Rest&gt;
    struct extract_impl&lt;n, n, T, Rest...&gt;
    {
        using type = T;
    };

public:
    using type = typename extract_impl&lt;0, idx, Types...&gt;::type;
};


Now that we have that, extracting from our type list is a simple subset operation based on the generalized template for extraction:

template &lt;std::size_t idx, class TypeList&gt;
struct type_list_extract;

template &lt;std::size_t idx, template &lt;class...&gt; class TypeList, class... Types&gt;
struct type_list_extract&lt;idx, TypeList&lt;Types...&gt;&gt;
{
    using type = typename extract&lt;idx, Types...&gt;::type;
};


For which we can provide a convenience alias:

template &lt;std::size_t idx, class TypeList&gt;
using type_list_extract_t = typename type_list_extract&lt;idx, TypeList&gt;::type;


That we can now use as follows:

int main()
{
    using list_t = type_list&lt;char, bool, void&gt;;

    static_assert( std::is_same&lt;char, type_list_extract_t&lt;0, list_t&gt;&gt;::value, "!" );
    static_assert( std::is_same&lt;bool, type_list_extract_t&lt;1, list_t&gt;&gt;::value, "!" );
    static_assert( std::is_same&lt;void, type_list_extract_t&lt;2, list_t&gt;&gt;::value, "!" );
    //type_list_extract_t&lt;3, list_t&gt;; // static_assert fails: index out of bounds
}


Final words

There are non-recursive ways to implement extraction (among other operations); they will most likely (possibly definitely!) require integer/index sequences. You can have a look at my answer for this question to see a non-recursive integer sequence implementation.

There are many more cool tricks to do with templates. Look on this very site or Stack Overflow!