2016-01-27 74 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