IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

[C++0x] Variadic template


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut [C++0x] Variadic template
    Bonsoir,

    J'essaye d'explorer et de comprendre les variadic templates (avec g++-4.5 ou g++4.6).

    Je connais std::function et std::bind, mais j'essaye d'avoir une classe pour encapsuler n'importe qu'elle fonction (pour l'instant libre, et non membre, c'est déjà suffisamment dur ).

    J'aimerais dans ma fonction execute :
    1: Sortir chacun des paramètres de la chaine params en fonction de son type (ArgsType) avec des istringstream logiquement
    2: Appeller la fonction (m_function) avec les paramètres obtenus précédement
    3: Récupérer la sortie de la fonction, la convertir en ReturnType
    4: Puis renvoyer le tout!

    Et je crois que je vais finir par m'arracher les cheveux avec le code ci-dessous, sachant que c'est dans la fonction execute que je bloque seulement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
        // Cette classe sert pour utiliser l'héritage, et donc avoir
        // une std::map< std::string, FunctionBase* > par exemple
        class FunctionBase
        {
        public :
            virtual ~FunctionBase() {}
     
            virtual std::string execute(const std::string &params) = 0;
        };
     
     
     
        template <typename ReturnType, typename... ArgsTypes>
        class Function : public FunctionBase
        {
        public:
            Function(   ReturnType (*f)(ArgsTypes...)     ) : m_function(f) {}
     
     
            virtual std::string execute(const std::string &params)    
            { 
                // C'est ici que je suis bloqué
     
                std::cout << " "<< std::endl; 
     
                return "";
            }
     
        private:
            ReturnType (*m_function)(ArgsTypes...);
        };
    Je ne sais pas si ma façon d'exprimer le problème était suffisamment bonne. Si vous souhaitais plus d'explications dîtes moi le.

    Si quelqu'un peut me donner une voie à suivre ou m'aider je serais grandement reconnaissant, même si c'est pour dire que je me trompe complètement de voie.
    Merci d'avance.

    P.S. Ceux qui l'auront remarqué c'est le tuto de Laurent Gomilla http://loulou.developpez.com/tutorie...eur3d/partie7/ que j'essaye de faire moi-même.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Les variadics templates c'est avant tout des templates, et avec les templates il faut utiliser la récurence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
        template<class... T>
        class AFaire{}
     
        template <typename ReturnType, typename... ArgsTypes>
        class Function : public FunctionBase
        {
        public:
            virtual std::string execute(const std::string &params)    
            {
                   std::istringstream iss(params);
                   ReturnType ret = ExecuteImpl<AFaire<ArgsTypes...>>::exec(iss, m_function);
            }
     
        private:
            template<class ArgsAFaire>
            class ExecuteImpl;
     
            template<>
            class ExecuteImpl< AFaire<> >
            {
                  template<class... ArgsFaits>
                  static ReturnType exec(std::istringstream& stream, ReturnType (*function)(ArgsTypes...), ArgsFaits... faits)
                  {
                           return function(stream, faits..., actuel);
                   }
             };
     
            template<class Actuel, class... ArgsAFaire>
            class ExecuteImpl< AFaire<Actuel, ArgsAFaire...> >
            {
                  template<class... ArgsFaits>
                  static ReturnType exec(std::istringstream& stream, ReturnType (*function)(ArgsTypes...), ArgsFaits... faits)
                  {
                           Actuel actuel;
                           stream >> actuel;
                           return ExecuteImpl< AFaire<ArgsAFaire...> >(stream, function, faits..., actuel);
                   }
             };
     
     
        };

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    Bonsoir, merci de t'intéresser à mon problème tout d'abord. J'arrive à comprendre le principe que tu utilise ici, mais j'ai un problème avec le compilo, il me dit qu'il y à des erreurs au niveau de la spécialisation avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<>
    class ExecuteImpl< AFaire<> >
    Avec error: explicit specialization in non-namespace scope ‘class pwr::Function<ReturnType, ArgsTypes, donc je vais me pencher là dessus, ce qui semblerait qu'on ne peut pas faire de spécialisation à l'intérieur de la classe.

    En tout cas merci beaucoup pour ton intervention très utile

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    Après avoir chercher un long moment j'arrive pas à arrêter la récurrence parce qu'il y à toujours des erreurs de compilations au niveau de la spécialisation.

    Apparemment on ne peut pas spécialiser une classe (ou fonction) template sans en avoir spécialisée celle dans laquelle ellei à été déclarée.

    J'ai trouvé ce post http://www.developpez.net/forums/d37...tion-template/ après plusieurs recherche, mais je n'arrive pas à appliquer la solution qui à été trouver.

    Merci d'avance de voir aide.

  5. #5
    Invité
    Invité(e)
    Par défaut
    En le sortant de la classe, ça devrait compiler, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    template <typename ReturnType, typename... ArgsTypes>
    class Function : public FunctionBase
    {
    //...
            template<class ArgsAFaire>
            class ExecuteImpl;
    //...
    };
     
    template<typename ReturnType, typename... ArgsTypes>
    template<>
    class Function<ReturnType, ArgsTypes...>::ExecuteImpl<ArgsAFaire<> >
    {
    //... même chose qu'avant
    };
     
    template<typename ReturnType, typename... ArgsTypes>
    template< class Actuel, class... ArgsAFaire>
    class Function<ReturnType, ArgsTypes...>::ExecuteImpl<ArgsAFaire<Actuel, ArgsAFaire...> >
    {
    //... même chose qu'avant
    };

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    J'en était arrivé au exactement au même pour la spécialisation, mais il reste une erreur sur cette dernière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename ReturnType, typename... ArgsTypes>
    template<> // Ligne 86
    class Function<ReturnType, ArgsTypes...>::ExecuteImpl<ArgsAFaire<> >
    {
        template<class... ArgsFaits>
        static ReturnType exec(std::istringstream& stream, ReturnType (*function)(ArgsTypes...), ArgsFaits... faits)
        {
            return function(stream, faits..., actuel);
        }
    };
    L'erreur est "Function.hpp:86:10: error: invalid explicit specialization before ‘>’ token"

    Merci pour ton aide, mais les templates restent encore un mystère pour moi

  7. #7
    Invité
    Invité(e)
    Par défaut
    Voci une version testé qui utilise une namespace private. Je crois voir d'où peut venir l'erreur en utilisant une classe interne mais je n'en suis pas sûr :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
     
    #include <sstream>
    #include <complex>
    #include <iostream>
     
    class FunctionBase
    {
    public :
        virtual ~FunctionBase() {}
     
        virtual std::string execute(const std::string &params) = 0;
    };
     
    namespace Private
    {
    template<class... Args>
    class AFaire
    {
    };
     
    template<class ArgsAFaire, class ReturnType, class... ArgsTypes>
    class ExecuteImpl;
     
    template< class ReturnType, class... ArgsTypes>
    struct ExecuteImpl< AFaire<>, ReturnType, ArgsTypes... >
    {
        template<class... ArgsFaits>
        static ReturnType exec(std::istringstream& stream, ReturnType (*function)(ArgsTypes...), ArgsFaits... faits)
        {
            return function(faits...);
        }
    };
     
    template<class Actuel, class... ArgsAFaire, class ReturnType, class... ArgsTypes>
    struct ExecuteImpl< AFaire<Actuel, ArgsAFaire...>, ReturnType, ArgsTypes... >
    {
        template<class... ArgsFaits>
        static ReturnType exec(std::istringstream& stream, ReturnType (*function)(ArgsTypes...), ArgsFaits... faits)
        {
            Actuel actuel;
            stream >> actuel;
            return ExecuteImpl< AFaire<ArgsAFaire...>, ReturnType, ArgsTypes... >::exec(stream, function, faits..., actuel);
        }
    };
    }
     
     
    template <typename ReturnType, typename... ArgsTypes>
    class Function : public FunctionBase
    {
    public:
        Function(   ReturnType (*f)(ArgsTypes...)     ) : m_function(f) {}
     
     
        virtual std::string execute(const std::string &params)
        {
    		std::istringstream iss(params);
     
    		ReturnType ret = Private::ExecuteImpl<Private::AFaire<ArgsTypes...>, ReturnType, ArgsTypes... >::exec(iss, m_function);
            std::ostringstream oss;
    		oss << ret;
    		return oss.str();
        }
     
    private:
        ReturnType (*m_function)(ArgsTypes...);
    };
     
     
    std::complex<int> foo(int i, char txt)
    {
    	std::cout << txt << std::endl;
    	return std::complex<int>(i,i);
    }
     
    int main(void)
    {
    	Function<std::complex<int> , int, char> func(&foo);
    	FunctionBase& base = func;
    	std::cout << base.execute("5 a") << std::endl;
     
    }
    EDIT : Une alternative, plus simple, est d'utiiser les deux fonctions suivantes(en les mettant dans la partie privée de la classe Fonction):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
        template<class... ArgsFaits>
        ReturnType executeImpl(std::istringstream& stream, AFaire<>, ArgsFaits... faits)
        {
            return m_function(faits...);
        }
     
     
     
        template<class Actuel, class... ArgsAFaire, class... ArgsFaits>
        ReturnType executeImpl(std::istringstream& stream, AFaire<Actuel, ArgsAFaire...>,ArgsFaits... faits)
        {
            Actuel actuel;
            stream >> actuel;
            return executeImpl(stream, AFaire<ArgsAFaire...>() ,faits..., actuel);
        }
    L'appel ne nécécessite juste d'envoyer un objet vide AFaire en plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ReturnType ret = executeImpl(iss, AFaire<ArgsTypes...>());
    Dernière modification par Invité ; 04/02/2011 à 17h22.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    Je viens de voir ton message et je ne peux que te dire un grand merci, surtout pour avoir continuer à m'aider, et d'avoir fournis un code comme celui-ci.

    Tu m'enlèves une énorme épine du pied! Encore mille merci! En espérant que cela puisse servir aussi à d'autres!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Hierarchie et variadic template
    Par victor_gasgas dans le forum Langage
    Réponses: 5
    Dernier message: 22/09/2010, 17h24
  2. C++ 0x variadic template
    Par victor_gasgas dans le forum Langage
    Réponses: 6
    Dernier message: 21/09/2010, 07h26
  3. [C++0x] Variadic template : un constructeur par type
    Par Florian Goo dans le forum Langage
    Réponses: 2
    Dernier message: 08/04/2009, 18h33
  4. Réponses: 2
    Dernier message: 10/01/2009, 13h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo