2 votes

Comment puis-je instancier une classe avec un pointeur de fonction membre en tant que template arg ?

J'ai

template <void (*T)(Entity *), typename Caller>
class Updater 
{
public:
    Updater(Caller c):m_caller(c){}
    void process(Entity * e)
    {
        (m_caller->*T)(e);              //Is this right?
    }
private:
    Caller m_caller;
};

Je comprends que je peux l'instancier comme

Foo f;
Updater<&Foo::Bar> updater(&f);

en supposant que Foo a

void Foo::Bar(Entity *e);

Mais qu'en est-il si la méthode souhaitée est tempérée ? Comme ceci

template <typename T>
void Bar(T t);

Comment dois-je l'installer ? Comme ceci: ?

Foo f;
Updater<&Foo::Bar<Entity *>> updater(&f);

Lorsque je fais cela dans mon code réel, j'obtiens

invalid template argument for ..., expected compile-time constant expression

Deux questions donc :

1, est (m_caller->*T)(e); correct ? Si ce n'est pas le cas, comment puis-je l'appeler ?

2, comment puis-je l'instancier ?

1voto

user2k5 Points 647
template <typename Caller, void (Caller::*Func)(Entity *)>
class Updater 
{
public:
    Updater(Caller *c):m_caller(c){}
    void process(Entity * e)
    {
        (m_caller->*Func)(e); // use pointer to member operator ->*
    }
private:
    Caller *m_caller;
};

// call like this
Foo f;
Updater<Foo, &Foo::Bar> updater(&f);

0voto

relaxxx Points 1392

éditer :

user2k5 a modifié sa réponse, je l'ai donc acceptée.

mon message précédent :

Grâce à user2k5, j'ai trouvé le bon code de fonctionnement,

L'échantillon de travail est le suivant : (Foo2 peut être remplacé par Foo)

#include <iostream>

struct Entity { int i; };

template < typename Caller, void (Caller::*Func)(Entity *)>
class Updater 
{
public:
    Updater(Caller *c):m_caller(c){}
    void process(Entity * e)
    {
        (m_caller->*Func)(e);
    }
private:
    Caller *m_caller;
};

struct Foo
{
    void bar(Entity * e) 
    {
        std::cout << e->i << std::endl;
    }
};

struct Foo2
{
    template <typename T>
    void bar(T t)
    {
        std::cout << t->i << std::endl;
    }
};

int main ()
{
    Foo2 f;
    Updater<Foo2, &Foo2::template bar<Entity *>> updater(&f);
    Entity e;
    e.i = 5;
    updater.process(&e);

    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X