2015-12-02 1 views
17

Considérez le code suivant:Pointeur vers les membres fonctionnels: que signifie 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> {}; 

Je n'ai absolument aucune idée de ce que (*C::*), (**C::*), (C::**) et (C::***) moyenne. Je voudrais un exemple d'un test<decltype(f)> dont value serait égal à 2, 3, 4 et 5. De plus, dans ce cas, comment est la syntaxe pour f qui appelle la fonction membre?

Répondre

18

Tenir compte 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); 
} 

Voici les types:

R(C::*)(Args...) - Un pointeur sur une fonction membre.
R(*C::*)(Args...) - Un pointeur vers un membre de données qui est un pointeur de fonction.
R(**C::*)(Args...) - Un pointeur vers un membre de données qui est un pointeur vers un pointeur de fonction.
R(C::**)(Args...) - Un pointeur vers un pointeur vers une fonction membre.
R(C::***)(Args...) - Un pointeur vers un pointeur vers un pointeur vers une fonction membre.

Pour appeler ceux-ci, envisager 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))(); 
} 

Notez que dans chaque cas, si vous avez une variable avec la valeur de la &[s::]testN, vous pouvez remplacer (&[s::]testN) approprié à cette variable. Notez également que pour test2 et test3, je déréférencé jusqu'à obtenir la fonction de retour plutôt que le pointeur de fonction à des fins d'illustration.

+0

Merci! Pourriez-vous donner un exemple si 's' a un membre de fonction' int f (int x) {return x;} ', et' testN' s'y réfère, quelle est la syntaxe pour exécuter 'testN' sur une variable? – Vincent

+0

@Vincent, j'arrivais à ça. Une seconde. – chris