I\'m aware that sizeof...(Args...)
yields the number of types in a C++0x packed template argument list, but I wanted to implement it in terms of other features
You didn’t declare a base case. You have a template-free overload of your num_args
function but when calling a function num_args<T...>()
this will never be found, for obvious reasons: it will always try to instantiate a function template.
You can however specialise your function template to perform the desired operation.
template <>
constexpr size_t num_args<>()
{
return 0;
}
However, this won’t work either since here you’re specialising a parameterless function template and such a template doesn’t exist: your other function template num_args
always has at least one argument, H
.
In order to really make this work you need partial specialisations, and these only exist for class templates. So this is what you need here.
template <typename T>
struct num_args_t;
template <>
struct num_args_t {
static size_t const value = 0;
};
template <typename H, typename T...>
struct num_args_t {
static size_t const value = num_args_t<T...>::value + 1;
};
template <typename T...>
constexpr size_t num_args() {
return num_args_t<T...>::value;
}
Konrad's answer should get you going, but I think the more idiomatic way such things are usually expressed is with static member constants, so I just wanted to present that solution:
#include <type_traits>
template <typename...> struct arg_size; // no primary definition needed
template <typename T, typename ...Args> struct arg_size<T, Args...>
: public std::integral_constant<std::size_t, 1 + arg_size<Args...>::value> { };
template <> struct arg_size<>
: public std::integral_constant<std::size_t, 0> { };
Then you get your argument pack size via arg_size<Args...>::value
.