2016-04-22 112 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"; 
}