I am trying to define two overload for a template function. First overload is generated if functor passed as an argument has no parameter otherwise second overload is generated. I started to implement like this :
template <typename R, typename... Types>
constexpr size_t argumentCount(R (*f)(Types...))
{
return sizeof...(Types);
}
template <typename Function>
typename std::enable_if<argumentCount<Function>() == 0, int>::value = 0 > callFunc(Function fu)
{
fu();
}
template <typename Function, typename... Params>
typename std::enable_if<argumentCount<Function>() == 0, int>::value = 0 > callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
This does not compile for several reasons including parse error.What I want to do is,
callFunc([](){});
will call overload 1 while callFunc([](int value1,int value2){});
will call overload 2.
How can I achieve this ?
If you can add a level of indirection... what about using tag-dispatching instead of SFINAE?
I mean, something as follows
#include <iostream>
#include <type_traits>
template <typename F>
void callFunc_helper (F fu, std::true_type)
{
std::cout << "zero version" << std::endl;
fu();
}
template <typename F, typename... Prs>
void callFunc_helper (F fu, std::false_type, Prs && ... params)
{
std::cout << "non zero version" << std::endl;
fu(std::forward<Prs>(params)...);
}
template <typename F, typename... Prs>
void callFunc (F fu, Prs && ... params)
{ callFunc_helper(fu, std::integral_constant<bool, 0u == sizeof...(Prs)>{},
std::forward<Prs>(params)...); }
int main ()
{
callFunc([]{});
callFunc([](int, int){}, 0, 1);
}
Obviously you can use std::integral_constant<bool, 0u == argumentCount<Function>()>{}
if you really want to check the number of the functional arguments instead of the number of the following parameters (but why?).