2016-04-22 137 views
2

我想知道是否有方法在C++ 11中获取函数的参数数量?获取函数参数计数

例如,对于功能foo我想argCount为3。

#include <iostream> 
void foo(int a, int b, int c) 
{ 

} 
int main() 
{ 
    size_t argCount=MAGIC(foo); 
    return 0; 
} 

在此先感谢。

+0

为此目的应该是有益的? –

+1

@πάνταῥεῖ,我知道至少有一个这样的应用程序,在重元编程 – SergeyA

+5

如果有几个重载在参数数量上有所不同,那么“MAGIC”应该返回什么? –

回答

2

您可以通过使用一个可变参数函数模板获得这些信息。

#include <iostream> 

template <typename R, typename ... Types> constexpr size_t getArgumentCount(R(*f)(Types ...)) 
{ 
    return sizeof...(Types); 
} 

//----------------------------------  
// Test it out with a few functions. 
//----------------------------------  

void foo(int a, int b, int c) 
{ 
} 

int bar() 
{ 
    return 0; 
} 

int baz(double) 
{ 
    return 0; 
} 

int main() 
{ 
    std::cout << getArgumentCount(foo) << std::endl; 
    std::cout << getArgumentCount(bar) << std::endl; 
    std::cout << getArgumentCount(baz) << std::endl; 
    return 0; 
} 

输出:

3 
0 
1 

看到它http://ideone.com/oqF8E8工作。

更新

巴里建议使用:

template <typename R, typename ... Types> 
constexpr std::integral_constant<unsigned, sizeof ...(Types)> getArgumentCount(R(*f)(Types ...)) 
{ 
    return std::integral_constant<unsigned, sizeof ...(Types)>{}; 
} 

有了这个,你可以通过使用获取参数的数量:

// Guaranteed to be evaluated at compile time 
size_t count = decltype(getArgumentCount(foo))::value; 

// Most likely evaluated at compile time 
size_t count = getArgumentCount(foo).value; 
+0

太复杂了:)看到我的答案为简短的例子。 – SergeyA

+0

@SergeyA,感谢您的支持。它现在比你的回答更简单:) –

+0

非常真实! :)唯一的一点是,我的电话不会调用某个功能,而您的电话却是这样。你需要让你的constexpr,但这仍然不能保证它永远不会被称为 - 这就是为什么我更喜欢我的版本。但是,你的代码更简单。 – SergeyA

5

由于几个原因,这并没有什么意义。

对于初学者来说,这真的会有什么好处?您可能正在寻找某种反思,但这在C++中尚不存在。

主要的原因,这是没有意义的,但是,过载集:

void f(int); 
void f(int, int); 
std::cout << MAGIC(f); // what should this print?? 
+0

有一种方法可以做到这一点。 – SergeyA

+0

然而,你可以做到的事实并不意味着它是有意义的。但是,是的,你是对的。 – Ven

+1

它在模板元编程的很多应用中都非常完美。 – SergeyA

7

是的,它可以很容易地完成:

#include <cstddef> 
#include <iostream> 

template <class R, class... ARGS> 
struct function_ripper { 
    static constexpr size_t n_args = sizeof...(ARGS); 
}; 


template <class R, class... ARGS> 
auto constexpr make_ripper(R (ARGS...)) { 
    return function_ripper<R, ARGS...>(); 
} 

void foo(int, double, const char*); 

void check_args() { 
    constexpr size_t foo_args = decltype(make_ripper(foo))::n_args; 

    std::cout << "Foo has " << foo_args << " arguments.\n"; 
}