2015-12-02 19 views
17

Si consideri il seguente codice:Puntatore ai membri delle funzioni: cosa significa `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> {}; 

Non ho assolutamente idea di cosa (*C::*), (**C::*), (C::**) e (C::***) dire. Vorrei un esempio di test<decltype(f)> il cui value sarebbe uguale a 2, 3, 4 e 5. Inoltre, in questo caso, qual'è la sintassi per f che chiamerebbe la funzione membro?

risposta

18

consideri 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); 
} 

Ecco i tipi:

R(C::*)(Args...) - Un puntatore a una funzione di membro.
R(*C::*)(Args...) - Un puntatore a un membro di dati che è un puntatore a funzione.
R(**C::*)(Args...) - Un puntatore a un membro di dati che è un puntatore a un puntatore di funzione.
R(C::**)(Args...) - Un puntatore a un puntatore a una funzione membro.
R(C::***)(Args...) - Un puntatore a un puntatore a un puntatore a una funzione membro.

di chiamare queste, prendere in considerazione un 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))(); 
} 

Nota che in ogni caso, se si dispone di una variabile con il valore del competente &[s::]testN, è possibile sostituire (&[s::]testN) con quella variabile. Si noti inoltre che per test2 e test3, ho desferito fino a ottenere la funzione indietro piuttosto che il puntatore di funzione a scopo illustrativo.

+0

Grazie! Potresti dare un esempio se 's' ha una funzione membro' int f (int x) {return x;} ', e' testN' si riferisce ad essa, qual è la sintassi per eseguire 'testN' su una variabile? – Vincent

+0

@Vincent, ci stavo arrivando. Un secondo. – chris