I use C ++ idiom detection , create a metafunction to determine the number of arguments to an arbitrary caller. So far I have (full, compiled code at http://ideone.com/BcgDhv ):
static constexpr auto max_num_args = 127;
struct any { template <typename T> operator T() { } };
template <typename F, typename... Args>
using callable_archetype = decltype( declval<F>()(declval<Args>()...) );
template <typename F, typename... Args>
using is_callable_with_args = is_detected<callable_archetype, F, Args...>;
template <typename F, size_t I = 0, typename... Args>
struct count_args
: conditional<is_callable_with_args<F, Args...>::value,
integral_constant<size_t, I>,
count_args<F, I+1, Args..., any>
>::type::type
{ };
template <typename F, typename... Args>
struct count_args<F, max_num_args, Args...> : integral_constant<size_t, max_num_args> { };
This works great when none of the arguments being invoked have references to lvalue:
void foo(int i, int j) { }
static_assert(count_args<decltype(foo)>::value == 2, "");
But when any of the arguments is lvalue references, this fails (for obvious reasons, since the called archetype has a replacement change):
void bar(char i, bool j, double& k);
static_assert(count_args<decltype(bar)>::value == 3, "doesn't work");
Does anyone know how to generalize this idea to make it work with lvalue references?