2014-03-25 36 views
11

具有該功能的定義:如何推導C++中的函數參數類型?

void f(int) { } 

我想定義:

int a; 

但如果函數定義更改爲:

void f(double) { } 

變量定義必須成爲:

double a; 

也就是說,「a」的類型必須與「f」函數的第一個參數相同。 我需要像下面這樣的東西:

decltype_of_argument<f, 0> a; 

在C++中可能嗎?

+1

decltype_of_argument是不可能的,在這裏解釋同樣的原因:HTTP://計算器.com/a/22631749/2694444 – galop1n

+0

所以如果f需要一個獸人,你會想要一個獸人? – Theolodis

+0

@ galop1n只適用於'f'被重載或函數重載'operator()' –

回答

3

使用模板?

template< typename T > 
void f(T) 
{ 
    T a; 
} 
+1

我不認爲OP想要這個。他沒有說'a'在'f'裏面。 – deepmax

+0

嗯,確實好點。 @ user3459257你能澄清這個問題嗎? – stijn

0

如何使模板功能?

template <typename T> 
void f(T t); 
2

其中一種方法是使用typedef作爲函數參數的類型。例如

typedef int TParm; 

void f(TParm); 

TParm a; 

您可以爲該類型選擇任何名稱。例如parm_t等。重要的是不會有名稱衝突。

在這種情況下,如果要更改參數的類型,只需更改typedef。

或者,如果你的編譯器支持別名,你也可以寫

using TParm = int; 

void f(TParm); 

TParm a; 

而且你可以用在命名空間或類中的函數。:)比如

struct IFunction 
{ 
    typedef int parm_t; 
    static void f(parm_t = parm_t()) {} 
}; 

//... 

IFunction::parm_t a; 
IFunction::f(a); 
+0

這可能是最接近OP的要求,但我認爲這會更好地考慮這個需求......我的意思是double和int可以在需要時施放。 – Theolodis

3

這取決於你想要什麼在哪裏使用該變量。如果是在功能的模板可能是一個不錯的選擇:

template<typename T> 
void foo(T) { 
    T a; 
} 

另外,如果你是功能之外,要真正知道這個要求,你可以使用Boost.TypeTraits,即function_traits<void (int)>::arg1_type會給int

+1

使用'function_traits :: arg1_type'來獲得'int' ?!爲什麼他不寫'int'? – deepmax

+0

@MM。因爲這是簡單的形式。實際上,你可以有一個typedef或者一個函數指針,甚至可以指向一個不太明顯的模板。 – johannes

19

您可以通過模板元編程獲取類型:

template <class F> struct ArgType; 

template <class R, class T> 
struct ArgType<R(*)(T)> { 
    typedef T type; 
}; 

void f(int) {} 

#include <type_traits> 
#include <iostream> 

int main() { 

    // To prove 
    std::cout << std::is_same< ArgType<decltype(&f)>::type, int >::value << '\n'; 

    // To use 
    ArgType<decltype(&f)>::type a; 
} 

根據你想使用它,你就需要專門這個豆蔻模板其他調用實體如成員福nunction poitner,具有更多參數的函數,函數等。在Boost庫中有更復雜的方法,參見例如。https://stackoverflow.com/a/15645459/1838266

注意:所有這些實用程序只在函數/可調用名稱明確映射到單個函數簽名時才起作用。如果一個函數被重載或者一個仿函數有多個operator(),那麼必須通過明確地轉換成正確的簽名來挑選正確的函數/操作符,這使得通過模板找出部分簽名非常沒用。這適用於某種方式的模板爲好,雖然得到的簽名的明確secialized可調用的可能仍然是有用的,例如:

template <unsigned N, class F> struct ArgType; //somewhat more sophisitcated 

template <class T> void f(int, T); 

ArgType<0, decltype(&f<double>)> //int - ArgType has it's use here 
ArgType<1, decltype(&f<double>)> //double - here it's useless... 
+0

+1優秀,這就是答案!我試圖寫這個,但你更快。 – deepmax

+0

注意:如果'f'被重載,它將會是'ArgType (&f))> :: type a;'這顯然不太有用,顯然... –

+0

@ MatthieuM。感謝提示,galop1n和我對這個問題的評論提到了這個問題,爲了澄清答案,我添加了它。 –