Get a new tuple containing all but first element of a tuple - c++

Given a std::tuple<A, B, ...> foo is there any generic (templated) function or technique in C++14 to get a new tuple std::tuple<B, ...> bar which contains all but the first element of foo? Or, perhaps something in Boost?
I've written a helper function using parameter packs and some template metaprogramming to do this, but I'd love to throw all of that stuff away!
Here's what I'm currently doing. I define a helper function unshift_tuple() which returns a tuple containing all but the first element of the tuple passed to the function. The implementation of unshift_tuple() uses a helper function unshift_tuple_with_indices() which takes a parameter pack containing the tuple indices to extract; the sequential_integer_list helper type is used to generate the appropriate index list parameter pack using template metaprogramming. Ugly!
#include <tuple>
template <size_t... Integers>
struct integer_list {};
template <size_t N, size_t... Args>
struct sequential_integer_list : sequential_integer_list<N - 1, N - 1, Args...> {};
template <size_t... Args>
struct sequential_integer_list<0, Args...> { typedef integer_list<Args...> type; };
template <typename FirstElement, typename... Elements, size_t... Indices>
static std::tuple<Elements...> unshift_tuple_with_indices(
const std::tuple<FirstElement, Elements...>& tuple,
integer_list<Indices...> index_type)
{
return std::make_tuple(std::get<Indices + 1>(tuple)...);
}
template <typename FirstElement, typename... Elements>
std::tuple<Elements...>
unshift_tuple(const std::tuple<FirstElement, Elements...>& tuple)
{
return unshift_tuple_with_indices(tuple,
typename sequential_integer_list<sizeof...(Elements)>::type());
}
int main(int, char *[])
{
std::tuple<int, std::string, double> foo(42, "hello", 3.14);
std::tuple<std::string, double> bar = unshift_tuple(foo);
}
To be clear, this code works just fine. I just wish very much to delete it (or any portion of it) and use something built-in instead, if possible!
Edit
Jarod42 pointed out the existence of std::integer_list in C++14 which simplifies the implementation to something like:
#include <cstddef>
#include <tuple>
#include <utility>
template <typename T1, typename... T, size_t... Indices>
std::tuple<T...> unshift_tuple_with_indices(
const std::tuple<T1, T...>& tuple, std::index_sequence<Indices...>)
{
return std::make_tuple(std::get<Indices + 1>(tuple)...);
}
template <typename T1, typename... T> std::tuple<T...>
unshift_tuple(const std::tuple<T1, T...>& tuple)
{
return unshift_tuple_with_indices(tuple,
std::make_index_sequence<sizeof...(T)>());
}

In C++17, you might do
template <typename T1, typename... Ts>
std::tuple<Ts...> unshift_tuple(const std::tuple<T1, Ts...>& tuple)
{
return std::apply([](auto&&, const auto&... args) {return std::tie(args...);}, tuple);
}
std::apply might be implemented in C++14.
Else, in C++14, there is std::index_sequence which avoids to write your own version, which simplifies your code to something like:
namespace details
{
template <typename Tuple, size_t... Indices>
auto unshift_tuple_with_indices(
const Tuple& tuple,
std::index_sequence<Indices...> index_type)
{
return std::make_tuple(std::get<Indices + 1>(tuple)...);
}
}
template <typename T, typename... Ts>
std::tuple<Ts...> unshift_tuple(const std::tuple<T, Ts...>& tuple)
{
return details::unshift_tuple_with_indices(tuple, std::index_sequence_for<Ts...>());
}

In C++14, there is a class template called std::integer_sequence that does similar to what you are doing with sequential_integer_list. You can find the reference in here.
In light of your code, it is possible to reduce and rely on pure meta-programming.
template <typename First, typename ... Elements>
struct unshift_tuple_impl
{
using type = std::tuple<Elements...>;
};
template <typename First, typename ... Elements>
std::tuple<Elements...>
unshift_tuple(const std::tuple<First, Elements...>& tuple)
{
return typename unshift_tuple_impl<First, Elements...>::type{};
}

Related

Subset a Variadic template given a constexpr boolean selection function

Suppose we have a variadic templated class like
template<class...Ts>
class X{
template<size_t I>
constexpr bool shouldSelect();
std::tuple<TransformedTs...> mResults; // this is want I want eventually
};
where the implementation of shouldSelect is not provided, but what it does is that, given an index i referring to the ith element of the variadic Ts, tells you whether we should select it to the subset.
I want to do a transformation on Ts such that only classes Ts at indexes that results in shouldSelect returning true should be selected. Is there an easy way to do this?
For example, if shouldSelect returns true for I = 1,2,4, and Ts... = short, int, double, T1, T2, then I want to get a TransformedTs... that is made up of int, double, T2. Then I can use this TransformedTs... in the same class.
If you're able to use C++17, this is pretty easy to implement using a combination of if constexpr and expression folding.
Start with some helper types, one with parameters to track the arguments to X::shouldSelect<I>(), and the other with a type to test.
template <typename T, size_t I, typename...Ts>
struct Accumulator {
using Type = std::tuple<Ts...>;
};
template <typename T>
struct Next { };
Then an operator overload either adds the type to the accumulator, or not with if constexpr:
template <typename TAcc, size_t I, typename... Ts, typename TArg>
decltype(auto) operator +(Accumulator<TAcc, I, Ts...>, Next<TArg>) {
if constexpr (TAcc::template shouldSelect<I>()) {
return Accumulator<TAcc, I + 1, Ts..., TArg>{};
} else {
return Accumulator<TAcc, I + 1, Ts...>{};
}
}
Finally, you can put it all together with a fold expression and extract the type with decltype:
template <template <typename... Ts> class T, typename... Ts>
constexpr decltype(auto) FilterImpl(const T<Ts...>&) {
return (Accumulator<T<Ts...>, 0>{} + ... + Next<Ts>{});
}
template<typename T>
using FilterT = typename decltype(FilterImpl(std::declval<T>()))::Type;
Usage:
using Result = FilterT<X<int, double, bool, etc>>;
Demo: https://godbolt.org/z/9h89zG
If you don't have C++17 available to you, it's still possible. You can do the same sort of conditional type transfer using a recursive inheritance chain to iterate though each type in the parameter pack, and std::enable_if to do the conditional copy. Below is the same code, but working in C++11:
// Dummy type for copying parameter packs
template <typename... Ts>
struct Mule {};
/* Filter implementation */
template <typename T, typename Input, typename Output, size_t I, typename = void>
struct FilterImpl;
template <typename T, typename THead, typename... TTail, typename... OutputTs, size_t I>
struct FilterImpl<T, Mule<THead, TTail...>, Mule<OutputTs...>, I, typename std::enable_if<( T::template shouldSelect<I>() )>::type >
: FilterImpl<T, Mule<TTail...>, Mule<OutputTs..., THead>, (I + 1)>
{ };
template <typename T, typename THead, typename... TTail, typename... OutputTs, size_t I>
struct FilterImpl<T, Mule<THead, TTail...>, Mule<OutputTs...>, I, typename std::enable_if<( !T::template shouldSelect<I>() )>::type >
: FilterImpl<T, Mule<TTail...>, Mule<OutputTs...>, (I + 1)>
{ };
template <typename T, typename... OutputTs, size_t I>
struct FilterImpl<T, Mule<>, Mule<OutputTs...>, I>
{
using Type = std::tuple<OutputTs...>;
};
/* Helper types */
template <typename T>
struct Filter;
template <template <typename... Ts> class T, typename... Ts>
struct Filter<T<Ts...>> : FilterImpl<T<Ts...>, Mule<Ts...>, Mule<>, 0>
{ };
template <typename T>
using FilterT = typename Filter<T>::Type;
Demo: https://godbolt.org/z/esso4M

Exclude first n arguments from parameter pack

I have a function foo that calls a function bar with a subset of types passed into foo's variadic template. For example:
template <typename... T>
void foo() {
// ...
template <size_t start_idx, typename... T>
using param_pack = /*Parameter pack with T[start_idx]...T[N]*/
auto b = bar<param_pack<2, T...>>();
// ...
}
Is there a way to extract a "sub-parameter pack". In the above case
if T = [int float char double] then param_pack<2, T...> = [char double]
[EDIT]
My goal is to be able to use something like this to match event handlers. For example
struct ev {};
template <typename... T>
struct event : ev {
std::tuple<T...> data_;
event(T&&... d) : data_(std::make_tuple(std::forward<T>(d)...)) {}
};
template <typename... Functor>
struct handler {
std::tuple<Functor...> funcs_;
handler(Functor&&... f) : funcs_(std::make_tuple(std::forward<Functor>(f)...)) {}
void handle_message(ev* e) {
auto ptrs = std::make_tuple(
dynamic_cast<event<param_pack<1, typename function_traits<F>::args>>*>(e)...
);
match(ptrs);
}
};
Here function_traits::args get a parameter pack for the function arguments and match iterates over the the tuple funcs_ checking if the dynamic_cast was successful and executing the first successful function. I already have these implemented.
The handlers are something like
[] (handler* self, <ARGS>) -> void {
// ...
}
I am essentially trying to get rid of the self argument.
Set aside the fact that it lacks a check on the index N for simplicity, here is a possible solution based on a function declaration (no definition required) and an using declaration:
template<std::size_t N, typename... T, std::size_t... I>
std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>
sub(std::index_sequence<I...>);
template<std::size_t N, typename... T>
using subpack = decltype(sub<N, T...>(std::make_index_sequence<sizeof...(T) - N>{}));
The good part of this approach is that you have not to introduce a new type designed around a tuple, then specialize it somehow iteratively.
It follows a minimal, working example that uses the code above:
#include<functional>
#include<tuple>
#include<cstddef>
#include<type_traits>
template<std::size_t N, typename... T, std::size_t... I>
std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>
sub(std::index_sequence<I...>);
template<std::size_t N, typename... T>
using subpack = decltype(sub<N, T...>(std::make_index_sequence<sizeof...(T) - N>{}));
int main() {
static_assert(std::is_same<subpack<2, int, float, char, double>, std::tuple<char, double>>::value, "!");
}
See a full example up and running on wandbox.
The extended version that includes a check on the index N would look like this:
template<std::size_t N, typename... T, std::size_t... I>
std::enable_if_t<(N < sizeof...(T)), std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>>
sub(std::index_sequence<I...>);
That is the type you can see in the first example once wrapped in a std::enable_if_t, nothing more. Again, declaration is enough, no definition required.
EDIT
If you want to use your own class template instead of an std::tuple, you can easily modify the code to do that:
#include<functional>
#include<tuple>
#include<cstddef>
#include<type_traits>
template<typename...>
struct bar {};
template<template<typename...> class C, std::size_t N, typename... T, std::size_t... I>
std::enable_if_t<(N < sizeof...(T)), C<std::tuple_element_t<N+I, std::tuple<T...>>...>>
sub(std::index_sequence<I...>);
template<template<typename...> class C, std::size_t N, typename... T>
using subpack = decltype(sub<C, N, T...>(std::make_index_sequence<sizeof...(T) - N>{}));
int main() {
static_assert(std::is_same<subpack<bar, 2, int, float, char, double>, bar<char, double>>::value, "!");
}
EDIT
According to the code added to the question, the solution above is still valid. You should just define your event class as it follows:
struct ev {};
template <typename>
struct event;
template <typename... T>
struct event<std::tuple<T...>>: ev {
// ...
};
This way, when you do this:
event<param_pack<1, typename function_traits<F>::args>>
You still get a tuple out of param_pack (that is the subpack using declaration in my example), but it matches the template partial specialization of event and the parameter pack is at your disposal as T....
This is the best you can do, for you cannot put a parameter pack in an using declaration. Anyway it just works, so probably it can solve your issue.
You may do something like:
template <std::size_t N, typename ... Ts> struct drop;
template <typename ... Ts>
struct drop<0, Ts...>
{
using type = std::tuple<Ts...>;
};
template <std::size_t N, typename T, typename ... Ts>
struct drop<N, T, Ts...>
{
using type = typename drop<N - 1, Ts...>;
};
// Specialization to avoid the ambiguity
template <typename T, typename... Ts>
struct drop<0, T, Ts...>
{
using type = std::tuple<T, Ts...>;
};
Here is a quick but not particularly reusable solution.
template <typename Pack, std::size_t N, std::size_t... Is>
void invoke_bar_impl(std::index_sequence<Is...>) {
bar<std::tuple_element_t<N + Is, Pack>...>();
}
template <std::size_t N, typename... Ts>
void invoke_bar() {
auto indices = std::make_index_sequence<sizeof...(Ts) - N>();
invoke_bar_impl<std::tuple<Ts...>, N>(indices);
}

How can I arbitrarily sort a tuple's types?

One thing that really annoys me about C++ is that an empty struct/class takes up space.
So, I have this idea that std::tuple (or some variant, since it's (and the compiler's) implementation is highly implementation dependent) might be able to save the day, which it sort of does, but there are issues due to packing and alignment. Because of how compilers will align the items in the struct, having a empty next to a non-empty next to an empty next to a non-empty will be larger than 2 empties next to 2 non-empties.
Because of this, I need a way to reorder the types based on some criteria. Sorting the entire list based on size isn't necessary (and may in some cases be detrimental) so I need some generic way to reorder the tuple's type list but still access it as if the type list was in the original order.
I looked around a bit and haven't found anything like this and I'm at a loss. Ideas on how to accomplish this?
Example
struct A{};
struct B{};
// Need to be reordered based on some criteria.
std::tuple<A, int, B, float> x;
// In this case move all of the empty objects together like:
// std::tuple<A, B, int, float> x;
// but still have get<1>(x) return the `int` and get<2>(x) return `B`.
static_assert(std::is_same<decltype(get<0>()), A>::value, "0 should be type A");
static_assert(std::is_same<decltype(get<1>()), int>::value, "1 should be type int");
static_assert(std::is_same<decltype(get<2>()), B>::value, "2 should be type float");
static_assert(std::is_same<decltype(get<3>()), float>::value, "3 should be type B");
The reason this cannot be done by hand is that this could be part of a template and the elements in tuple may be empty or not, based on the parameters:
template <typename A, typename B, typename C, typename D>
class X
{
// Need to have this auto arranged given some criteria
// like size or move all of the empties together.
tuple<A, B, C, D> x;
public:
template<int i>
auto get() -> typename std::tuple_element<i, decltype(x)>
{
return get<i>(x);
}
};
// What are these types? Who knows. This could be buried in some
// template library somewhere.
X<T1, T2, T3, T4> x;
Building on what Barry did.
So from here I'd need a mapping meta-function to use the original
indices, how would I do that?
First, some helpers to facilitate index mapping. And because I'm lazy, I modified typelist slightly.
template <typename... Args>
struct typelist {
static constexpr std::size_t size = sizeof...(Args);
};
template<class T, std::size_t OldIndex, std::size_t NewIndex>
struct index_map_leaf {
using type = T;
static constexpr std::size_t old_index = OldIndex;
static constexpr std::size_t new_index = NewIndex;
};
template<class... Leaves>
struct index_map : Leaves... {};
Given a properly built index_map, converting from old index to new index is simple, leveraging template argument deduction and overload resolution:
template<std::size_t OldIndex, std::size_t NewIndex, class T>
index_map_leaf<T, OldIndex, NewIndex>
do_convert_index(index_map_leaf<T, OldIndex, NewIndex>);
template<std::size_t OldIndex, class IndexMap>
using converted_index_t = decltype(do_convert_index<OldIndex>(IndexMap()));
converted_index_t<OldIndex, IndexMap>::new_index is, well, the new index.
To build the index map, we do it in in three steps. We start by transforming the types into type-index pairs.
template<class... Ts, std::size_t... Is>
typelist<index_map_leaf<Ts, Is, 0>...>
do_build_old_indices(typelist<Ts...>, std::index_sequence<Is...>);
template<class TL>
using build_old_indices =
decltype(do_build_old_indices(TL(), std::make_index_sequence<TL::size>()));
Next, we partition the pairs. We need a metafunction that applies another metafunction to its arguments' nested typedef type rather than the arguments themselves.
// Given a metafunction, returns a metafunction that applies the metafunction to
// its arguments' nested typedef type.
template<class F>
struct project_type {
template<class... Args>
using apply = typename F::template apply<typename Args::type...>;
};
Given this, partitioning a typelist of index_map_leafs is simply partition_t<LeafList, project_type<F>>.
Finally, we transform the partitioned list, adding the new indices.
template<class... Ts, std::size_t... Is, std::size_t...Js>
typelist<index_map_leaf<Ts, Is, Js>...>
do_build_new_indices(typelist<index_map_leaf<Ts, Is, 0>...>,
std::index_sequence<Js...>);
template<class TL>
using build_new_indices =
decltype(do_build_new_indices(TL(), std::make_index_sequence<TL::size>()));
Bringing it all together,
template<class TL, class F>
using make_index_map =
apply_t<quote<index_map>, build_new_indices<partition_t<build_old_indices<TL>,
project_type<F>>>>;
With a little utility to convert the arguments of an arbitrary template to a type list:
template<template<class...> class T, class... Args>
typelist<Args...> do_as_typelist(typelist<T<Args...>>);
template<class T>
using as_typelist = decltype(do_as_typelist(typelist<T>()));
We can do the partitioning only once, by constructing the reordered tuple type directly from the index_map.
template<class Tuple, class F>
struct tuple_partitioner {
using map_type = make_index_map<as_typelist<Tuple>, F>;
using reordered_tuple_type = apply_t<project_type<quote<std::tuple>>,
as_typelist<map_type>>;
template<std::size_t OldIndex>
using new_index_for =
std::integral_constant<std::size_t,
converted_index_t<OldIndex, map_type>::new_index>;
};
For example, given
using original_tuple = std::tuple<int, double, long, float, short>;
using f = quote<std::is_integral>;
using partitioner = tuple_partitioner<original_tuple, f>;
The following assertions hold:
static_assert(partitioner::new_index_for<0>() == 0, "!");
static_assert(partitioner::new_index_for<1>() == 3, "!");
static_assert(partitioner::new_index_for<2>() == 1, "!");
static_assert(partitioner::new_index_for<3>() == 4, "!");
static_assert(partitioner::new_index_for<4>() == 2, "!");
static_assert(std::is_same<partitioner::reordered_tuple_type,
std::tuple<int, long, short, double, float>>{}, "!");
Demo.
P.S. Here's my version of filter:
template<typename A, typename F>
using filter_one = std::conditional_t<F::template apply<A>::value,
typelist<A>, typelist<>>;
template<typename F, typename... Args>
concat_t<filter_one<Args, F>...> do_filter(typelist<Args...>);
template <typename TL, typename F>
using filter_t = decltype(do_filter<F>(TL()));
First, let's start with the basics. We need a way to turn a template template (std::tuple) into a metafunction class:
template <template <typename...> class Cls>
struct quote {
template <typename... Args>
using apply = Cls<Args...>;
};
And a typelist:
template <typename... Args>
struct typelist { };
And something to go between them:
template <typename F, typename TL>
struct apply;
template <typename F, typename... Args>
struct apply<F, typelist<Args...>> {
using type = typename F::template apply<Args...>;
};
template <typename F, typename TL>
using apply_t = typename apply<F, TL>::type;
So that given some typelist, we can just have:
using my_tuple = apply_t<quote<std::tuple>, some_typelist>;
Now, we just need a partitioner on some criteria:
template <typename TL, typename F>
struct partition {
using type = concat_t<filter_t<TL, F>,
filter_t<TL, not_t<F>>
>;
};
Where concat:
template <typename... Args>
struct concat;
template <typename... Args>
using concat_t = typename concat<Args...>::type;
template <typename... A1, typename... A2, typename... Args>
struct concat<typelist<A1...>, typelist<A2...>, Args...> {
using type = concat_t<typelist<A1..., A2...>, Args...>;
};
template <typename TL>
struct concat<TL> {
using type = TL;
};
filter:
template <typename TL, typename F>
struct filter;
template <typename TL, typename F>
using filter_t = typename filter<TL, F>::type;
template <typename F>
struct filter<typelist<>, F> {
using type = typelist<>;
};
template <typename A, typename... Args, typename F>
struct filter<typelist<A, Args...>, F> {
using type = concat_t<
std::conditional_t<F::template apply<A>::value,
typelist<A>,
typelist<>>,
filter_t<typelist<Args...>, F>
>;
};
And not_:
template <typename F>
struct not_ {
template <typename Arg>
using apply = std::conditional_t<F::template apply<Args>::value,
std::false_type,
std::true_type>;
};
Which, given some_typelist of types that you want to put in your tuple becomes:
using my_tuple = apply_t<
quote<std::tuple>,
partition_t<
some_typelist,
some_criteria_metafunc_class
>>;

How can I get the index of a type in a variadic class template?

I have a variadic Engine template class:
template <typename ... Components> class Engine;
I'd like to assign a number to each component at compile time which is equivalent to their ordering. This would be returned when making the following call:
template <typename Component> int ordinal();
So for example if:
Engine<PositionComponent, PhysicsComponent, InputComponent> engine;
was declared, the call:
engine.ordinal<PhysicsComponent>();
would return 1 and a similar call with InputComponent instead of PhysicsComponent would return 2.
Is it possible, and if yes, how would one go about it?
In Boost.Mp11, this is a short one-liner (as always):
template <typename... Components>
struct Engine {
template <typename Component>
static constexpr int ordinal() {
return mp_find<Engine, Component>::value;
}
};
Note that if Component is absent, this will return sizeof...(Components). If desired, you can add a static assertion to verify this.
My original answer follows below the fold...
So you want to find the index of Component in Components...?
template <typename... >
struct index;
// found it
template <typename T, typename... R>
struct index<T, T, R...>
: std::integral_constant<size_t, 0>
{ };
// still looking
template <typename T, typename F, typename... R>
struct index<T, F, R...>
: std::integral_constant<size_t, 1 + index<T,R...>::value>
{ };
Usage:
template <typename Component>
size_t ordinal() { return index<Component, Components...>::value; }
As constructed, trying to get the ordinal of a Component not in Components... will be a compile error. Which seems appropriate.
My goal below is to keep things in the compile-time realm as much as possible.
This is an alias to remove some boilerplate. std::integral_constant is a wonderful std type that stores a compile-time determined integer-type:
template<std::size_t I>
using size=std::integral_constant<std::size_t, I>;
Next, a index_of type, and an index_of_t that is slightly easier to use:
template<class...>struct types{using type=types;};
template<class T, class Types>struct index_of{};
template<class T, class...Ts>
struct index_of<T, types<T, Ts...>>:size<0>{};
template<class T, class T0, class...Ts>
struct index_of<T, types<T0, Ts...>>:size<
index_of<T,types<Ts...>>::value +1
>{};
This alias returns a pure std::integral_constant, instead of a type inheriting from it:
template<class T, class...Ts>
using index_of_t = size< index_of<T, types<Ts...>>::value >;
Finally our function:
template <class Component>
static constexpr index_of_t<Component, Components...>
ordinal() const {return{};}
it is not only constexpr, it returns a value that encodes its value in its type. size<?> has a constexpr operator size_t() as well as an operator(), so you can use it in most spots that expect integer types seamlessly.
You could also use:
template<class Component>
using ordinal = index_of_t<Component, Components...>;
and now ordinal<Component> is a type representing the index of the component, instead of a function.
I'm adding this for completeness sake, it utilizes C++11's constexpr functionality, and a few stl functions. I feel it is a little cleaner than the other solutions.
//Same type
template <typename Target,typename T,typename ...Rest>
constexpr typename std::enable_if<std::is_same<Target,T>::value, size_t>
_ordinal(){
return 0;
}
//Different types
template <typename Target,typename T,typename ...Rest>
constexpr typename std::enable_if<!std::is_same<Target,T>::value, size_t>
_ordinal(){
return 1+_ordinal<Target,Rest...>();
}
UNTESTED:
template <int, typename>
constexpr int index_of() { return -1; } // type not found
template <int N, typename Component, typename Cur, typename... Components>
constexpr int index_of() {
return std::is_same<Component, Cur>::value ? N : index_of<N+1, Component, Components...>();
}
template <typename... Components>
template <typename Component>
constexpr int engine<Components...>::ordinal() {
return index_of<0, Component, Components...>();
}
I could have used structs, but I find this much cleaner (without all the ::type ugliness).
If you want a compile-time error when the type is not found, change ordinal to:
template <typename... Components>
template <typename Component>
constexpr int engine<Components...>::ordinal() {
static_assert(index_of<0, Component, Components...>()!=-1, "invalid component");
return index_of<0, Component, Components...>();
}

How to automatically deduce T in this forwarding function?

Given this code
template <typename T, typename... Args>
auto make_vector(Args&&... args)
{
return std::vector<T>{std::forward<Args>(args)...};
}
I don't want to type make_vector<int>(1, 2, 3, 4). How to get rid of T?
You could do like this:
template <typename Head, typename... Tail> struct Types{
typedef typename std::decay<Head>::type ReturnType;
//typedef std::decay_t<Head> ReturnType; // C++14 equivalent
};
template <typename... Args>
auto make_vector(Args&&... args)
{
return std::vector<typename Types<Args...>::ReturnType>{std::forward<Args>(args)...};
}
Note that,the code select first parameter type as vector template parameter, all the Args type need same or convertable.