2015-12-02 17 views
17

Xét đoạn mã sau:Con trỏ để hoạt động thành viên: những gì hiện `R (* C :: *) (Args ...)` nghĩa là gì?

template <class> 
struct test: std::integral_constant<int, 0> {}; 
template<class R, class C, class... Args> 
struct test<R(C::*)(Args...)>: std::integral_constant<int, 1> {}; 
template<class R, class C, class... Args> 
struct test<R(*C::*)(Args...)>: std::integral_constant<int, 2> {}; 
template<class R, class C, class... Args> 
struct test<R(**C::*)(Args...)>: std::integral_constant<int, 3> {}; 
template<class R, class C, class... Args> 
struct test<R(C::**)(Args...)>: std::integral_constant<int, 4> {}; 
template<class R, class C, class... Args> 
struct test<R(C::***)(Args...)>: std::integral_constant<int, 5> {}; 

Tôi hoàn toàn không có ý tưởng về những gì (*C::*), (**C::*), (C::**)(C::***) có ý nghĩa. Tôi muốn có ví dụ về số test<decltype(f)>value sẽ bằng 2, 3, 45. Ngoài ra, trong trường hợp đó, cú pháp của f sẽ gọi hàm thành viên như thế nào?

Trả lời

18

Cân nhắc this example:

struct s { 
    void test1(); 
    void(*test2)(); 
    void(**test3)(); 
}; 

int main() { 
    static_assert(test<decltype(&s::test1)>::value == 1); 
    static_assert(test<decltype(&s::test2)>::value == 2); 
    static_assert(test<decltype(&s::test3)>::value == 3); 

    auto test4 = &s::test1; 
    static_assert(test<decltype(&test4)>::value == 4); 

    auto test5 = &test4; 
    static_assert(test<decltype(&test5)>::value == 5); 
} 

đây là các loại:

R(C::*)(Args...) - Một con trỏ tới một hàm thành viên.
R(*C::*)(Args...) - Một con trỏ tới thành viên dữ liệu là con trỏ hàm.
R(**C::*)(Args...) - Một con trỏ tới thành viên dữ liệu là con trỏ trỏ đến con trỏ hàm.
R(C::**)(Args...) - Một con trỏ trỏ đến con trỏ tới hàm thành viên.
R(C::***)(Args...) - Một con trỏ trỏ đến con trỏ tới con trỏ tới hàm thành viên.

Để gọi này, xem xét một slightly modified example:

struct s { 
    void test1() {std::cout << "test1\n";} 
    void(*test2)() = [] {std::cout << "test2\n";}; 

    void(*test3Helper)() = [] {std::cout << "test3\n";}; 
    void(**test3)() = &test3Helper; 

    void test4() {std::cout << "test4\n";} 
    void test5() {std::cout << "test5\n";} 
}; 

int main() { 
    s obj; 

    auto test4 = &s::test4; 

    auto test5Helper = &s::test5; 
    auto test5 = &test5Helper; 

    (obj.*(&s::test1))(); 
    (*(obj.*(&s::test2)))(); // note that the dereference is unnecessary 
    (**(obj.*(&s::test3)))(); // note that the second dereference is unnecessary 
    (obj.**(&test4))(); 
    (obj.***(&test5))(); 
} 

Lưu ý rằng trong mỗi trường hợp, nếu bạn có một biến với giá trị của hợp &[s::]testN, bạn có thể thay (&[s::]testN) với biến đó. Cũng lưu ý rằng đối với test2 và test3, tôi đã bỏ qua cho đến khi lấy lại hàm thay vì con trỏ hàm cho mục đích minh họa.

+0

Cảm ơn! Bạn có thể đưa ra một ví dụ nếu 's' có một hàm thành viên' int f (int x) {return x;} ', và' testN' đề cập đến nó, cú pháp để thực hiện 'testN' trên một biến là gì? – Vincent

+0

@Vincent, tôi đã đạt được điều đó. Một giây. – chris

Các vấn đề liên quan