Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove the last type of a template parameter pack

Tags:

c++

templates

I want to use the types of a template parameter pack as parameters to a different template, but cut off the last parameter.

For example:

template <class... Ts> struct some_template;

template <class... Ts> struct foo
{
    using bar = some_template<magically_get_all_but_last(Ts)...>;
};

// I might be missing a few "typename"s, but you get the idea.
static_assert(std::is_same<foo<int, bool, std::string>::bar, some_template<int,bool> >::value); 

Note that this is the opposite of getting only the last parameter.

like image 864
Tobias Brandt Avatar asked Aug 15 '15 12:08

Tobias Brandt


People also ask

Can template parameter have default value?

Like function default arguments, templates can also have default arguments. For example, in the following program, the second parameter U has the default value as char.

What is type template parameter?

The first template parameter is the type of elements the container stores and the second template parameter is the defaulted allocator a container of the standard template library has. Even the allocator has a default value such as in the case of a std::vector. The allocator depends on the type of elements.

Can we pass non-type parameters to templates?

However, template type parameters are not the only type of template parameters available. Template classes and functions can make use of another kind of template parameter known as a non-type parameter.

How many kinds of template parameters are there in C++?

The data type variable is defined by an angled bracket in a parameter (t) and the keyword “template” in the C++ programming language. What types of templates are there in CPP? Function templates, class templates, and, as of C++14, variable templates are the three categories of templates.


2 Answers

Here is a simple approach which use std::tuple_element<I, Tuple> together with std::index_sequence<sizeof...(Ts) - 1 to get all but the last type in a list of variadic arguments. Since the parameter pack for the indices is needed, there is an extra indirection which is put into a base but could be anywhere.

template <class T, class... Ts> struct foobase;
template <std::size_t... I, class... Ts>
struct foobase<std::index_sequence<I...>, Ts...> {
    using bar = some_template<typename std::tuple_element<I, std::tuple<Ts...>>::type...>;
};

template <class... Ts> struct foo
    : foobase<std::make_index_sequence<sizeof...(Ts) - 1>, Ts...>
{
};
like image 129
Dietmar Kühl Avatar answered Sep 21 '22 22:09

Dietmar Kühl


Here is my solution which uses C++11:

template <typename ...P>
struct dummy {};

template <template <typename ...> class Obj, typename T, typename ...P>
struct internal;

template <template <typename ...> class Obj, typename ...P1, typename T, typename ...P2>
struct internal<Obj, dummy<P1...>, T, P2...>
{
    using type = typename internal<Obj, dummy<P1..., T>, P2...>::type;
};

template <template <typename ...> class Obj, typename ...P1, typename T, typename L>
struct internal<Obj, dummy<P1...>, T, L>
{
    using type = Obj<P1..., T>;
};

template <template <typename ...> class T, typename ...P>
struct subst_all_but_last
{
    using type = typename internal<T, dummy<>, P...>::type;
};

Use like this:

using bar = typename subst_all_but_last<some_template, Ts...>::type;

instead of

using bar = some_template<magically_get_all_but_last(Ts)...>;
like image 22
HolyBlackCat Avatar answered Sep 23 '22 22:09

HolyBlackCat