получить количество параметров любого вызываемого объекта во время компиляции в С++ 14

82
11

Мне интересно, может ли функция "сопоставить образец" и вызываемый объект извлекать (во время компиляции) количество аргументов функции. Другими словами, я хотел бы создать мета-функцию count_arg, которая возвращает количество аргументов переданной функции.

Рассмотрим этот код:

#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;
}

Этот пример работает, но если я попробую с fmin:

std::cout << " fmin arity:" << count_arg<LIFT_FUN(fmin)>::value << std::endl;

(используя g++ 4.9.2: g++ flip.cpp -o flip -std = С++ 14) Я получаю эту ошибку:

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;

Есть идеи?

РЕДАКТИРОВАТЬ

Следуя предложению Vittorio, я попытался реализовать get_arity (получить функцию arity из параметра шаблона):

std::cout << "   g arity:" << get_arity<decltype(g)>::value << std::endl;
std::cout << "fmin arity:" << get_arity<decltype(fmin)>::value << std::endl;

Но у меня еще проблема с fmin. Если я перейду с этим переводом (возвращающаяся лямбда не является более общей):

template <typename F>
decltype(auto) flip(F f)
{
return [f](int a, int b){
return f(b, a);
};
}

мой код компилируется...

Итак, теперь моя проблема заключается в том, что мне нужно найти способ извлечения аргументов og из общих лямбда. Есть идеи?

спросил(а) 2015-12-27T17:57:00+03:00 3 года, 11 месяцев назад
0
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема