2015-12-02 10 views
17

Rozważmy następujący kod:Wskaźnik do elementów funkcji: co znaczy "R (* C :: *) (Args ...)"?

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> {}; 

mam absolutnie żadnego pojęcia, co (*C::*), (**C::*), (C::**) i (C::***) myśli. Chciałbym przykład test<decltype(f)>, którego value będzie równa 2, 3, 4 i 5. A w takim razie, w jaki sposób składnia dla f wywoła funkcję członka?

Odpowiedz

18

Rozważmy 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); 
} 

Oto typy:

R(C::*)(Args...) - Wskaźnik do funkcji składowej.
R(*C::*)(Args...) - Wskaźnik do elementu danych, który jest wskaźnikiem funkcji.
R(**C::*)(Args...) - Wskaźnik do elementu danych, który jest wskaźnikiem do wskaźnika funkcji.
R(C::**)(Args...) - Wskaźnik do wskaźnika do funkcji składowej.
R(C::***)(Args...) - Wskaźnik do wskaźnika do wskaźnika do funkcji składowej.

Aby połączyć te rozważmy 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))(); 
} 

pamiętać, że w każdym przypadku, jeśli masz zmienną o wartości odpowiedniej &[s::]testN można zastąpić (&[s::]testN) z tej zmiennej. Zauważ też, że dla test2 i test3, odwoływałem się do momentu otrzymania funkcji zamiast wskaźnika funkcji w celach ilustracyjnych.

+0

Dzięki! Czy mógłby podać przykład, jeśli 's' ma element członkowski' int f (int x) {return x;} ', a' testN' odnosi się do niego, jaka jest składnia do wykonania 'testN' na zmiennej? – Vincent

+0

@Vincent, do tego doszedłem. Sekundę. – chris