I'm wondering if it's possible to "pattern matching" function and callable object to extract (at compile time) the number of arguments of a function. In other words I would like to create a meta-function called count_arg that return the number of arguments of the function passed.
Consider this code:
#include <iostream>
#include <functional>
#include <type_traits>
#define LIFT_FUN(f) decltype(f)
template<typename T>
struct count_arg : public count_arg<decltype(&T::operator())>
{
};
template<typename R, typename ...Args>
struct count_arg<R(Args...)>
{
static const size_t value = sizeof...(Args);
};
template <typename C, typename R, typename... Args>
struct count_arg<R(C::*)(Args...) const>
{
static const size_t value = sizeof...(Args);
};
template<typename R, typename ...Args>
struct count_arg<R(*)(Args...)>
{
static const size_t value = sizeof...(Args);
};
template<typename R, typename ...Args>
struct count_arg<R(&)(Args...)>
{
static const size_t value = sizeof...(Args);
};
template <typename T>
struct show_type;
template <typename F>
decltype(auto) flip(F f)
{
return [f](auto a, auto b){
return f(b, a);
};
}
int minus(int a, int b, int c)
{
return a - b + c;
}
struct Minus
{
int operator()(int a, int b) const
{
return a - b;
}
};
int main()
{
int a{5}, b{3};
auto g = [](int a, int b){
return a - b;
};
auto fmin = flip(g);
std::cout << minus(a, b, 0) << std::endl;
std::cout << fmin(a, b) << std::endl;
std::cout << "minus arity:" << count_arg<LIFT_FUN(minus)>::value << std::endl;
std::cout << " g arity:" << count_arg<LIFT_FUN(g)>::value << std::endl;
std::cout << "Minus arity:" << count_arg<LIFT_FUN(Minus{})>::value << std::endl;
}
This example works, but if I try with fmin :
std::cout << " fmin arity:" << count_arg<LIFT_FUN(fmin)>::value << std::endl;
(using g++ 4.9.2: g++ flip.cpp -o flip -std=c++14) I'm getting this error:
flip.cpp: In instantiation of ‘struct count_arg<flip(F) [with F = main()::<lambda(int, int)>]::<lambda(auto:1, auto:2)> >’:
flip.cpp:83:61: required from here
flip.cpp:9:8: error: decltype cannot resolve address of overloaded function
struct count_arg : public count_arg<decltype(&T::operator())>
^
flip.cpp: In function ‘int main()’:
flip.cpp:83:36: error: ‘value’ is not a member of ‘count_arg<flip(F) [with F = main()::<lambda(int, int)>]::<lambda(auto:1, auto:2)> >’
std::cout << " fmin arity:" << count_arg<LIFT_FUN(fmin)>::value << std::endl;
Any idea?
EDIT
Following the suggestion of Vittorio, I've tryed the get_arity implementation (Get function arity from template parameter):
std::cout << " g arity:" << get_arity<decltype(g)>::value << std::endl;
std::cout << "fmin arity:" << get_arity<decltype(fmin)>::value << std::endl;
But I still to have problem with fmin. If I change flip in this way (the returning lambda is not more generic):
template <typename F>
decltype(auto) flip(F f)
{
return [f](int a, int b){
return f(b, a);
};
}
my code compiles ...
So my problem in now that I have to find a way to extract the number og arguments from a generic lambdas. Any idea?