Как получить количество аргументов функции из `decltype (<funtion>)`? - PullRequest
4 голосов
/ 10 июля 2020

Допустим, у меня есть следующее объявление функции:

template<typename signature>
int foo();

Учитывая вышеупомянутую функцию, можно ли определить foo таким образом, чтобы она возвращала количество аргументов функции которые были переданы в параметре шаблона decltype?

Таким образом, пример использования может выглядеть так:

int bar(int a, int b) 
{
    return a + b;
}

int jar(int a)
{
    return a * a;
}

int main() 
{
    std::cout << foo<decltype(bar)>() << std::endl; // Desired output: 2
    std::cout << foo<decltype(jar)>() << std::endl; // Desired output: 1
}

Edit:

Спасибо всем за ответы. Кажется, они работают. Однако я забыл упомянуть еще один вариант использования.

Допустим, я хочу получить количество аргументов следующей функции:

int __stdcall car(int a, int b, int c)
{
    return a * b + c;
}

Ответы пока не работают с такой функцией, которая использует соглашение __stdcall.

Есть идеи, почему и что можно с этим сделать?

Ответы [ 2 ]

4 голосов
/ 10 июля 2020

Для этого (т.е. с decltype) данного foo недостаточно. Вам понадобится что-то вроде следующих черт.

template<typename> struct funtion_args final {};

template<typename ReType, typename... Args>
struct funtion_args<ReType(Args...)> final
{
   static constexpr std::size_t noArgs = sizeof...(Args);
};

Используемый sizeof... оператор в аргументы шаблона * Variadi c, чтобы получить количество аргументов . И затем вы можете напрямую получить количество аргументов, например

std::cout << funtion_args<decltype(bar)>::noArgs << "\n"; // output: 2

, или упаковать в foo

template<typename signature>
constexpr std::size_t foo() noexcept
{
   return funtion_args<signature>::noArgs;
}

( См. Живую демонстрацию )

Лучший подход

Если вы хотите меньше печатать (т.е. без decltype), более удобный способ получения количества аргументов свободной функции, вы можете сделать следующее

template <typename ReType, typename... Args> 
constexpr auto foo(ReType(*)(Args...)) noexcept
{
   return sizeof...(Args);
}

Теперь вы можете удобно вызывать foo с другими функциями в качестве аргументов

std::cout << foo(bar) << "\n"; // output: 2

( См. Живую демонстрацию )

2 голосов
/ 10 июля 2020

Конечно, просто foo() вызовите подходящий тип черты. Например:

template <typename T>
struct foo_helper;

template <typename T, typename... Args>
struct foo_helper<T(Args...)> {
    static constexpr std::size_t arg_count = sizeof...(Args);
};

template <typename T>
std::size_t foo() {
    return foo_helper<T>::arg_count;
}
...