Question

Je suis en train de stocker des pointeurs de fonctions membres par des modèles comme celui-ci: (Ceci est une version simplifiée de mon code réel)

template<class Arg1>
void connect(void (T::*f)(Arg1)) 
{
    //Do some stuff
}

template<class Arg1>
void connect(void (T::*f)()) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Alors je veux faire comme ce qui suit pour chaque méthodes surchargées dans GAPP:

connect(&GApp::foo); 

pour appeler cette foo() est ok, mais comment puis-je appeler cela pour foo(double d)? Pourquoi pas le travail à la suite?

connect((&GApp::foo)(double)); 

Il me donnera

  

erreur de syntaxe: 'double' doit être précédée d' ')'

Je ne comprends pas la syntaxe qui doit être utilisé ici. Cela peut être un question stupide, mais peut-il me aider à ce sujet?

Était-ce utile?

La solution

Votre code comme écrit ne compile pas. J'ai fait des « hypothèses » sur ce que vous vouliez faire, et ont changé le code.

Pour résumer, vous pouvez appeler la fonction correcte en spécifiant explicitement le type de paramètre de fonction:

connect<double> (&GApp::foo);

Si les méthodes de connexion sont membres d'un modèle de classe, alors il est nécessaire de spécifier le type de classe une fois:

template <typename T> class A
{
public:
  template<class Arg1>
  void connect(void (T::*f)(Arg1)) 
  {
    //Do some stuff
  }

  void connect(void (T::*f)()) 
  {
    //Do some stuff
  }
};

class GApp
{
public:
    void foo() {}
    void foo(double d) {}
};


int main ()
{
  A<GApp> a;
  a.connect (&GApp::foo);            // foo ()
  a.connect<double> (&GApp::foo);    // foo (double)
}

Mise à jour:

En réponse au nouvel échantillon de code, l'ensemble des informations est transmis. Le cas « rare » est le cas « signal_void » comme cela est où le signal a un argument de modèle, mais la fonction de membre ne. Par conséquent, nous cas particulier cet exemple et nous avons terminé. Ce qui suit compile maintenant:

template <class Arg = void>
class signal {};
signal<double> signal_double;
signal<> signal_void;

// Arg1 is deduced from signal<Arg1> and then we use it in the declaration
// of the pointer to member function
template<class T, class Arg1>
void connect ( signal<Arg1>& sig, T& obj, void (T::*f)(Arg1) ) {}

// Add special case for 'void' without any arguments
template<class T>
void connect (signal<> & sig, T& obj, void (T::*f)()) {}


void bar ()
{
  GApp myGApp;

  //Connecting foo()
  connect(signal_void, myGApp, &GApp::foo); // Matches second overload

  //Connecting foo(double)
  connect(signal_double, myGApp, &GApp::foo); // Matches first overload
}

Autres conseils

Le C ++ Programming Language, 3E, Section 7.7, P159:

  

Vous pouvez prendre l'adresse d'une fonction surchargée en affectant ou initialiser un pointeur de fonction. Dans ce cas, le type de la cible est utilisé pour sélectionner parmi l'ensemble des fonctions surchargées. Par exemple:

void f(int);
int f(char);

void (*pf1)(int) = &f;  // void f(int);
int (*pf2)(char) = &f;  // int f(char);
void (*pf3)(char) = &f; // error: no void f(char)

Pour autant que je sais (ai pas vérifié), de même pour les fonctions membres. Donc, la solution est probablement de diviser entre deux lignes:

connect((&GApp::foo)(double));

devient:

void (GApp::*tmp)(double) = &GApp::foo;
connect(tmp);

Jamais les variables appeler tmp; -)

Je suppose que le casting de newacct est sûr aussi, pour la même raison. Coulée à void (GApp::*)(double) est défini comme étant le même que l'initialisation d'un type temporaire de type void (GApp::*)(double). Depuis l'expression utilisée pour l'initialiser est &GApp::foo, je pense la même magie d'appliquer à la distribution comme s'applique à toute autre initialisation avec une fonction surchargée. Stroustrup ne dit pas « initialiser une variable pointeur à la fonction », dit-il « initialiser un pointeur à la fonction ». Ce qui devrait inclure temporaires.

Donc, si vous préférez une doublure:

connect((void (GApp::*)(double))(&GApp::foo));

Cependant, je suppose que la norme a la même idée de cohérence que moi, et je n'ai pas vérifié.

Vous pouvez jeter explicitement le pointeur, de le laisser savoir lequel choisir, comme ceci:

connect((void (GApp::*)(double))&GApp::foo);

disclaimer: ont pas testé

Cela fonctionne,

    typedef void (GApp::*MemberFunctionType)(double); 
    MemberFunctionType pointer = &GApp::foo;


  connect(MemberFunctionType);

Pourquoi?

EDIT

hmm .. ouais. Il est le même que la solution de newacct. Quelqu'un peut-il donner une solution pls?

Utilisation de boost :: bibliothèque de fonctions ...

#include <boost/function.hpp>

template<class Arg1>
void connect(boost::function1<void, Arg1*> fn) 
{
    //Do some stuff
}

template<class Arg1>
void connect(boost::function2<void, Arg1*, double> fn) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};


int main()
{
    boost::function1<void,GApp*> f1 = (void (GApp::*)(void)) &GApp::foo;
    boost::function2<void,GApp*,double> f2 = (void (GApp::*)(double)) &GApp:foo;
    connect(f1);
    connect(f2);
    return 0;
}

Mon code original est comme ça,

connecteurs ....

template<class T, class Arg1>
void connect(signal<Arg1>& sig,T& obj, void (T::*f)()) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

template<class T, class Arg1
void connect(signal<Arg1>& sig,T& obj, void (T::*f)(Arg1)) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

Signaux ...

signal<double> signal_double;
signal<> signal_void;

Application ...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Finaly, connexion ...

//Connecting foo()
        connect(signal_void, myGApp, &GApp::foo()); //Ok

//Connecting foo(double)
        connect(signal_double, myGApp, &GApp::foo()); // but ERROR!

Il est modèle Classs pour les signaux (qui ne sont pas mention ici). J'espère que maintenant il est plus clair la situation. (Ou est-ce même que previouse?). Cette seconde connexion fonctionnera s'il n'y a pas foo () (seulement foo (double)). C'est la chose mon code me faire du mal. : (

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top