如何从`decltype(<function>)` 获取函数参数的数量?

ars*_*v31 5 c++ templates arguments function count

假设我有以下函数声明:

template<typename signature>
int foo();
Run Code Online (Sandbox Code Playgroud)

鉴于上述函数,是否可以以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
}
Run Code Online (Sandbox Code Playgroud)

编辑:

感谢所有人的回复。他们似乎工作。但是,我忘了提及另一个用例。

假设我想获取以下函数的参数数量:

int __stdcall car(int a, int b, int c)
{
    return a * b + c;
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,答案似乎不适用于这种使用__stdcall约定的函数。

知道为什么以及可以做些什么吗?

JeJ*_*eJo 5

为此(即与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);
};
Run Code Online (Sandbox Code Playgroud)

在可变参数模板参数sizeof...上使用运算符,以获取参数的数量。然后你可以直接得到参数计数

std::cout << funtion_args<decltype(bar)>::noArgs << "\n"; // output: 2
Run Code Online (Sandbox Code Playgroud)

或装入 foo

template<typename signature>
constexpr std::size_t foo() noexcept
{
   return funtion_args<signature>::noArgs;
}
Run Code Online (Sandbox Code Playgroud)

见现场演示


更好的方法

如果您想要更少的输入(即没有decltype),一种更方便的获取自由函数参数计数的方法,您可以执行以下操作

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

现在您可以方便地foo使用其他函数作为参数调用

std::cout << foo(bar) << "\n"; // output: 2
Run Code Online (Sandbox Code Playgroud)

见现场演示


cdh*_*wie 2

当然,只要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;
}
Run Code Online (Sandbox Code Playgroud)