I'm new to variadic templates and for the sake of learning consider the following function
template <typename T, typename... args>
T* make_arr(args... arg) {
// Code to check if passed args are of the same type
T* arr = new T[sizeof...(arg)]{ arg... };
return arr;
}
I have two questions:
args...
, I mean without using <typename T>
? ... I used decltype(arg) but it didnt work ...Note: please edit the title question if it is not appropriate ... thanks
The only way I found is to make a helper function using SFINAE
//Basic function
template<typename T>
void allsame(T) {}
//Recursive function
template<typename T, typename T2, typename... Ts,
typename = std::enable_if_t<std::is_same<T, T2>::value>>
void allsame(T arg, T2 arg2, Ts... args)
{
allsame(arg2, args...);
}
You can then call it like so:
allsame(arg...);
The compiler will then throw an error if the types are not the same.
For 2), you could modfiy allsame
to return the type. The only drawback to this function is that it won't work if the type isn't default constructable.
template<typename T>
T allsame(T) { return{}; }
T allsame(T arg, T2 arg2, Ts... args)
Then, you can decltype(allsame(args...))
to get the type
First of all, you'll need these includes:
#include <type_traits>
#include <tuple>
then, let us declare variadic template to detect whether types are same or not:
template <typename ... args>
struct all_same : public std::false_type {};
template <typename T>
struct all_same<T> : public std::true_type {};
template <typename T, typename ... args>
struct all_same<T, T, args...> : public all_same<T, args ... > {};
now we can use static_assert
to detect if parameters types are same:
template <typename T, typename... args>
T* make_arr(args... arg) {
// Code to check if passed args are of the same type
static_assert(all_same<args ...>::value, "Params must have same types");
T* arr = new T[sizeof...(arg)]{ arg... };
return arr;
};
Finally, let us take return type of your function as first type of parameters - if all types are same we can take any of them. We use std::tuple
for this
template <typename... args>
typename std::tuple_element<0, std::tuple<args...> >::type * make_arr(args... arg) {
// Code to check if passed args are of the same type
static_assert(all_same<args ...>::value, "Params must have same types");
typedef typename std::tuple_element<0, std::tuple<args...> >::type T;
T* arr = new T[sizeof...(arg)]{ arg... };
return arr;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With