2016-01-27 72 views
4

我明白如何聲明一個函數的類型:怪異成員函數指針語法

typedef void (typedef_void_f)(); // typedef_void_f is void() 
using alias_void_f  = void(); // alias_void_f is void() 

而且它可以被用於聲明函數指針:

void function() { std::cout << __PRETTY_FUNCTION__ << '\n'; } 

typedef_void_f *a = function; // pointer to void() 
alias_void_f *b = function; // pointer to void() 

對於成員函數指針的語法稍微複雜一些:

struct S { void function() { std::cout << __PRETTY_FUNCTION__ << '\n'; } }; 

typedef void (S::*typedef_void_m_f)(); 
using alias_void_m_f = void (S::*)(); 

typedef_void_m_f c = &S::function; // pointer to S void() member function 
alias_void_m_f d = &S::function; // pointer to S void() member function 

這是我對C++函數指針的理解我認爲這已經足夠了。

但在p0172r0 technical paper我發現我不熟悉語法:

struct host { 
    int function() const; 
}; 

template <typename TYPE> 
constexpr bool test(TYPE host::*) { // <---- What is this?? 
    return is_same_v<TYPE, int() const>; 
} 

constexpr auto member = &host::function; 

test(member); 

據我瞭解的代碼中,test功能分裂的功能類型從的類型對象,其中的功能所屬,所以在模板test功能TYPE模板參數將void(),但如果我嘗試以下方法:

void my_test(void() S::*) {} 

my_test(&S::function); 

,我收到了一堆語法錯誤:

error: variable or field 'my_test' declared void 
void my_test(void() S::*) {} 
       ^
error: expected ')' before 'S' 
void my_test(void() S::*) {} 
        ^
error: 'my_test' was not declared in this scope 
    my_test(&S::function); 

所以很明顯,我不理解p0172r0的test函數的語法。

有人可以解釋template <typename TYPE> constexpr bool test(TYPE host::*)語法的細節嗎?

+0

不,我不問'T :: *'在模板參數中意味着什麼。 –

+0

對不起。沒有得到它很快重新打開。 – NathanOliver

+1

這不限於成員指針。如果你有'使用T = int()',那麼'T * p'是有效的,而'int()* p'是語法規則所禁止的。 – cpplearner

回答

3

TYPE host::*是指向類數據成員的指針。 TYPE是類成員的類型,host::*表示指向host成員的指針。所以TYPE host::*接受一個指向任何host

+0

那麼爲什麼'void my_test(void()S :: *)'不接受指向'S'的任何'void()'成員的指針? –

+0

@PaperBirdMaster據瞭解,一個指向類數據成員的指針和一個指向類成員函數的指針是不同的。我從來沒有見過你在任何我見過的代碼中嘗試使用的語法。 – NathanOliver

+0

@PaperBirdMaster我一直在測試,我不認爲C++允許這樣做。請參閱:http://coliru.stacked-crooked。com/a/5db4e74c2be52aaf – NathanOliver

1

成員試試這個:

constexpr void my_test(void (S::*)()) {} 

也就是說聲明一個參數的正確方法類型指針的S返回void不帶參數的成員函數。

http://ideone.com/EqfYmb

+0

因此,如果'my_test(void(S :: *)())'是聲明指向void()成員'S'的指針的正確方法,那麼shouldnt'模板 constexpr布爾測試(TYPE host :: *)'be'template constexpr bool test(TYPE(host :: *)())'?我不明白[p0172r0](http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0172r0.html)上的語法。 –

+0

@PaperBirdMaster我認爲可以像你說的那樣「拆分」這個類型,因爲模板扣除規則。 – imreal