Partage
  • Partager sur Facebook
  • Partager sur Twitter

Alias d'une instanciation d'une méthode template

    16 avril 2018 à 22:10:08

    Bonjour,

    Je suis confronté à la situation suivante. J'ai une classe contenant plusieurs méthodes, ainsi qu'une méthode qui me sert de wrapper. La déclaration ressemble à cela :

    class Foo{
    private:
      int method1(int);
      char method2(bool, int);
      void method3();
      //...et davantages...
    
      template<
        typename T,
        typename ...P,
        T (Foo::*)(P...)
      > T wrapper(P...);
    };

    Toutes ces fonctions sont en private. Ce que je souhaiterais faire, c'est créer pour chacune de ces méthodes (le wrapper exclu) une méthode publique, qui appellerait tout simplement la méthode wrappée. Bien entendu, je pourrais tout simplement faire comme cela pour chacune des méthodes :

    int Foo::wrap_method1(int arg){
      return wrapper<method1>(arg);
    }

    Mais cela impliquerait de faire un appel fonction supplémentaire. Ce que j'aimerais faire, c'est créer une sorte d'alias, c'est-à-dire associer à chaque méthode wrappée un nom (par exemple Foo::wrap_methodn à Foo::wrapper<methodn>). Ainsi :

    Foo foo;
    
    foo.wrap_method1(0);     //Cet appel...
    foo.wrapper<method1>(0); //Et cet appel (sans prendre en compte l'encapsulation)...
    
    /**
      ...ont le même comportement.
    **/

    ...et ce, sans utiliser #define.

    Merci de vos réponse, et bonne soirée.

    • Partager sur Facebook
    • Partager sur Twitter
      16 avril 2018 à 23:32:28

      Quel est le problème avec l'appel de fonction supplémentaire ? Si c'est pour des raisons d'optimisation, le compilateur sait très bien inliner le code.

      • Partager sur Facebook
      • Partager sur Twitter
        17 avril 2018 à 5:16:16

        Je n'en doute pas. En réalité, un appel de fonction supplémentaire ne me dérange pas tant que ça. En revanche, je trouve ça peu pratique d'écrire ces méthodes, sachant que cela revient à produire du code supplémentaire pour un truc simple que le compilateur pourrait faire parfaitement. Je me demandais juste s'il existait une manière de faire cela en C++ pur, c'est-à-dire, sans faire appel au spécificité du compilateur.
        • Partager sur Facebook
        • Partager sur Twitter
          17 avril 2018 à 10:33:55

          Utilise le perfect forwarding avec les variadic templates. Mais tu es tout de même obligé de mettre tes fonctions publiques.

          #include <iostream>
          
          class foo {
          public:
          	void f1(int, int, int) {
          		puts("f1");
          	}
          	void f2(bool, int, bool) {
          		puts("f2");
          	}
          
          public:
          	template <typename Function, typename... Args>
          	void call(Function f, Args&&... args)
          	{
          		(this->*f)(std::forward<Args>(args)...);
          	}
          };
          
          int main() {
          	foo f;
          
          	f.call(&foo::f1, 1, 2, 3);
          	f.call(&foo::f2, -1, false, -2);
          
          	return 0;
          }

          Ainsi, si tu as besoin de faire du code commun aux deux fonctions f1 et f2, tu peux le faire dans call. Mais bon je ne suis tout de même peu fan de la solution finale.


          Si tu peux déjà utiliser C++17, tu peux même profiter de std::invoke.

          -
          Edité par markand 17 avril 2018 à 10:36:16

          • Partager sur Facebook
          • Partager sur Twitter

          git is great because Linus did it, mercurial is better because he didn't.

            17 avril 2018 à 22:00:38

            Merci pour l'idée du std::forward. Bien que je suis parvenu à écrire mon wrapper correctement, je viens de le réécrire avec cette fonction.

            Cependant, dans ce cas, il n'y a pas énormement d'avantage. Autant écrire wrapper<method1> directement, ce sera tout aussi long que f.call(method1,...)...

            • Partager sur Facebook
            • Partager sur Twitter

            Alias d'une instanciation d'une méthode template

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown