2013-07-03 61 views
11

我理解函數類型的問題(例如它們顯示爲std::functionSignature模板參數):C++函數類型

typedef int Signature(int); // the signature in question 

typedef std::function<int(int)> std_fun_1; 
typedef std::function<Signature> std_fun_2; 

static_assert(std::is_same<std_fun_1, std_fun_2>::value, 
       "They are the same, cool."); 

int square(int x) { return x*x; } 

Signature* pf = square; // pf is a function pointer, easy 
Signature f;    // but what the hell is this? 
f(42);     // this compiles but doesn't link 

可變f不能被分配,但是可以被調用。奇怪的。那麼有什麼好處呢?

現在,如果我常量-資格typedef的,我還可以用它來建立其他類型的,但顯然沒有別的:

typedef int ConstSig(int) const; 

typedef std::function<int(int) const> std_fun_3; 
typedef std::function<ConstSig>  std_fun_4; 

static_assert(std::is_same<std_fun_3, std_fun_4>::value, 
       "Also the same, ok."); 

ConstSig* pfc = square; // "Pointer to function type cannot have const qualifier" 
ConstSig fc;   // "Non-member function cannot have const qualifier" 

已經打到我這裏什麼語言的偏僻的角落?這種奇怪的類型是如何調用的,我可以在模板參數之外使用它嗎?

+0

標準簡單地允許你*通過一個typedef到他們的簽名(實際上,功能型)聲明*函數。 – Xeo

回答

15

以下是標準中的相關段落。它幾乎說明了一切。

8.3.5/10

功能類型的類型定義也可以用來聲明功能,但不應被用來定義一個函數(8.4)。

實施例:

typedef void F(); 
F fv;   // OK: equivalent to void fv(); 
F fv { }  // ill-formed 
void fv() { } // OK: definition of fv 

的功能類型的類型定義,其聲明符包括CV限定符SEQ應僅用於聲明用於非靜態成員函數的函數類型,以聲明指向成員的指針的函數類型,或者聲明另一個函數typedef聲明的頂級函數類型。

實施例:

typedef int FIC(int) const; 
FIC f;    // ill-formed: does not declare a member function 
struct S { 
    FIC f;    // OK 
}; 
FIC S::*pm = &S::f; // OK 
+0

非常好。這正是我正在尋找的信息。謝謝。 – marton78

+0

謝謝!我應該早點注意到它。 – Bikineev

0

在你的情況下,std_fun_1std_fun_2是具有相同類型簽名的相同對象。它們都是std::function<int(int)>,並且都可以保存int(int)類型的函數指針或可調用對象。

pf是指向int(int)的指針。也就是說,它具有與std::function相同的基本用途,但沒有該類的機制或支持可調用對象的實例。

類似地,std_fun_3std_fun_4是具有相同類型簽名的相同對象,並且都可以保存類型爲int(int) const的函數指針或可調用對象。

同樣,pfcint(int) const類型的函數指針,它可以保存指向該類型函數的指針,但不包含可調用對象的實例。

但是ffc都是函數聲明。

行:

Signature fc; 

是相同的等價於:

int fc(int) const; 

這是一個名爲int(int) constfc功能的聲明。

這裏沒有什麼奇怪的事情發生在這裏。你只是發生在你可能已經理解的語法上,從你不習慣的角度來看。