1

I'm new to template metaprogramming. I was looking for a metafunction to check if parameter pack arguments are of a certain type (C++11 required). For this I use:

template<typename ...Ts>
void foo(Ts... args)
{
    static_assert(is_all_same<int, Ts...>::value, "Arguments must be of type int");
    // do something
}

I was thinking about using std::is_same as a template (pun intended) add the functionality for parameter packs. This is what I have right now:

template<typename T, typename... U>
struct is_all_same : std::false_type {};
 
template<typename T>
struct is_all_same<T, T...> : std::true_type {};

But it doesn't work. gcc says:

<source>:323:24: error: expansion pattern 'T' contains no parameter packs
  323 | struct is_all_same<T, T...> : std::true_type {};

What I don't understand is how to add specialisation for a parameter pack. Do I have to use recursion somehow?

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
glades
  • 3,778
  • 1
  • 12
  • 34

2 Answers2

2

I don't think you need specialization or recursion. You can just check if all types are the same as the first type:

#include <type_traits>
template <typename T, typename...U>
using is_all_same = std::integral_constant<bool, (... && std::is_same_v<T,U>)>;

The (... && expression) is a fold-expression. As a convenience, it's true for an empty pack, so is_all_same<int>::value is also true.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks but I can't use fold expressions because I require C++11 as I'm coding for an embedded system :/ – glades Mar 10 '22 at 12:43
0

You can first partially specialize is_all_same<T, T>, then partially specialize the case where the template parameter is variadic

#include <type_traits>

template<typename...>
struct is_all_same : std::false_type {};

template<>
struct is_all_same<> : std::true_type {};

template<typename T>
struct is_all_same<T> : std::true_type {};

template<typename T>
struct is_all_same<T, T> : std::true_type {};

template<typename T, typename... U>
struct is_all_same<T, T, U...> : is_all_same<T, U...> {};
康桓瑋
  • 33,481
  • 5
  • 40
  • 90