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

C++ Discussion :

Variadic templates et std::function


Sujet :

C++

  1. #1
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut Variadic templates et std::function
    Bonjour,

    Je cherche � faire marcher un code du genre :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    template<typename... args>
    int func(std::function<int(args...)> f)
    {
       return sizeof...(args); // juste pour tester
    }
    Avec ensuite :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    int f2(int a, int b, int c)
    {
        return a + b + c;
    }
    Le code suivant compile bien :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    std::function<int(int, int, int)> f3 = f2;
    func(f3); // renvoie bien 3
    En revanche, celui-ci ne compile pas :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    func(f2); /* error: no matching function for call to ‘func(int (&)(int, int, int))’
    test.cpp:45:25: note: candidate is:
    test.cpp:28:5: note: template<class ... args> int func(std::function<int(args ...)>)
    test.cpp:28:5: note:   template argument deduction/substitution failed:
    test.cpp:45:25: note:   mismatched types ‘std::function<int(args ...)>’ and ‘int (*)(int, int, int)’ */
    Et celui-ci non plus :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    func([](int a, int b, int c) { return f2(a,b,c); }); /* error: no matching function for call to ‘func(main()::<lambda(int, int, int)>)’
    test.cpp:44:68: note: candidate is:
    test.cpp:28:5: note: template<class ... args> int func(std::function<int(args ...)>)
    test.cpp:28:5: note:   template argument deduction/substitution failed:
    test.cpp:44:68: note:   ‘main()::<lambda(int, int, int)>’ is not derived from ‘std::function<int(args ...)>’ */
    Pour le premier cas, je peux fournir un overload :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    template<typename... args>
    int func(int (*f)(args...))
    {
        return sizeof...(args);
    }
    Pas tr�s �l�gant, mais �a marche. En revanche, pour le deuxi�me cas, je ne vois pas comment faire sans fournir l�ensemble des surcharges jusqu�� n arguments, ce qui est justement ce que je souhaitais �viter avec les templates variadic.

    Mon compilateur est gcc 4.7.2, je ne peux pas en changer. Des suggestions ?

  2. #2
    Membre �m�rite
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par d�faut
    Bonjour,

    Dans ton exemple, tu renvoies les nombre de param�tres de la fonction avec pour commentaire "juste pour tester".
    Quel est le but r�el derri�re ce test ?
    Il y a plusieurs mani�res de g�rer ce genre de probl�mes mais pour �a il faudrait voir qu'est-ce que c'est r�ellement cens� faire au final.

  3. #3
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Dans le code r�el, �a renvoie une lambda dont le r�le sera d�appeler f avec des param�tres lus depuis une structure, stock�s temporairement dans un vecteur, apr�s avoir v�rifi� un certain nombre de contraintes sur ces param�tres. En gros, l�id�e, c�est de d�coupler la partie � r�cup�ration et v�rification des param�tres � (qui viennent d�appels jsonrpc), assez syst�matique et r�p�titive, de la partie m�tier, et de la faire de mani�re g�n�rique (v�rification de pr�sence et type de chacun des arguments, appel de la fonction m�tier avec les arguments individuels si ok, sinon erreur).

    Oui, c�est un petit peu compliqu�, c�est pour �a que j�ai essay� de simplifier au maximum pour montrer le point qui me bloque actuellement.

  4. #4
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    F�vrier 2009
    Messages
    762
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2009
    Messages : 762
    Par d�faut
    Salut,

    Pourquoi pas quelque chose dans cette veine :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    template<class Fun>
    int func(Fun f)
    {
       return boost::function_traits<Fun>::arity; // pas sur de la syntaxe mais bon l'idée est là.
    }
    L'id�e est d'�tre simplement plus g�n�ral. D'habitude c'est de cette mani�re qu'on passe des fonctions en argument.

  5. #5
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Effectivement, j�avais n�glig� cette possibilit� (du fait que j�ai certains param�tres fix�s, le type de la valeur de retour fix�, etc).

    N�anmoins, ce n�est pas bon quand m�me :
    test.cpp: In instantiation of �int func(Fun) [with Fun = main()::<lambda(int, int, int)>]�:
    test.cpp:57:68: required from here
    test.cpp:43:53: error: �value� is not a member of �boost::function_types::function_arity<main()::<lambda(int, int, int)> >�
    (pour les non lambdas, �a fonctionne bien).

  6. #6
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Pour la question initiale, la r�ponse devient clair si tu te mets � la place du compilateur. On te donne un truc de type A et tu dois le faire matcher avec un type B<T>, tu fais comment ? Comment tu peut savoir � l'avance si un B<T0> va proposer un constructeur depuis un A ? Tu ne peux pas (tout tester n'est pas envisageable (*)). Quand tu lui passes un A=B<T0> la probl�matique dispara�t puisqu'on trouve un T qui fait parfaitement correspondre les types (**).

    Ta probl�matique de fond, c'est vraiment l'arit� ? Parce que je ne suis pas convaincu qu'il y ai une vraie solution � cette probl�matique. Si je passe un foncteur polymorphe avec un Arg... qui fait du forward, la fonction fait quoi ? Cependant, si la question c'est vraiment l'arit�, c'est une m�ta-fonction (***) qu'il faut chercher � faire, pas une fonction (c'est purement compile-time comme information).

    (*) Surtout qu'il faudrait ordonner les diff�rentes possibilit�s ensuite ...
    (**) Modulo le const, volatile, &, &&, mais le compilateur les ignore pour la proc�dure de correspondance.
    (***) Dans l'id�e il faut que tu envisages tout les cas possibles (que tu veux traiter) de foncteur, que tu fasses un my_meta_fn<> sp�cialis� pour chacun de ces cas avec un Arg... sur lequel faire un sizeof...(Arg).

  7. #7
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Je comprends le compilateur, mais j�ai quand m�me un manque (soit dans mon compilateur, soit dans le langage, soit dans ma connaissance de celui-ci, mais le fait que �a ne fonctionne pas non plus chez boost m�incite � pencher pour une des deux premi�res propositions).

    Le manque, c�est la capacit� de faire une sp�cialisation template pour une lambda dont on conna�trait les arguments et le type de retour. Je peux le faire pour un std::function et un pointeur de fonction, mais pas une lambda. C�est un peu dommage.

    Sinon, ma probl�matique n�est pas l�arit� (qui n��tait que pour mettre en �uvre le manque), ma probl�matique est globalement de r�cup�rer des arguments re�us dans une map et de rappeler une fonction avec les bons param�tres, apr�s avoir fait un certain nombre de v�rifications (en mode programmation d�fensive, justifi� car on est dans un contexte web). Au final je m�en sors en fournissant les diff�rentes surcharges possibles (et via un variant pour limiter le nombre de combinaisons). J�aurais aim� faire sans (ie, faire g�n�rer chaque variante par le compilateur), mais j�ai du mal � voir comment.

    Le pseudo-code suivant reproduit grosso-merdo ce que j�essaie de faire :
    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
     
    std::function<int(std::map<std::string, variant> const&)>
    createFunctor(std::map<std::string, ParamDescription> const& paramDescription, std::function f)
    {
       return [paramDescrition](std::map<std::string, variant> parameters)
       {
             for(param : paramDescription)
             {
                   if(/* everything ok with param, found in parameters with good type, etc... */)
                       accumulate(parameters[param.name];
             }
             if(everythingOk)
                 return f(param1, param2, param3…)
             else
                 report error;
       }
    }
    Pour l�instant j�accumule les param�tres dans une array et je les envoie en tant que variant. Comme je sp�cialise pour chaque nombre d�arguments, �a passe, et comme ma fonction n�est plus template, je profite de la conversion de ma lambda vers std::function, qui fait que �a fonctionne bien aussi. Mais c�est lourd puisque je dois cr�er explicitement pour chaque nombre d�arguments (soit actuellement 6*fonctions � maintenir), et id�alement chaque type de mon variant (ce qui donnerait � la louche 5^6 impl�mentations, ce qui n�est pas envisageable).

  8. #8
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par d�faut
    Tu as besoin de passer explicitement par des lambdas?
    Tu ne pourrai pas les convertir en std::function avant de les donner � ta fonction?

  9. #9
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Citation Envoy� par leternel Voir le message
    Tu as besoin de passer explicitement par des lambdas?
    Tu ne pourrai pas les convertir en std::function avant de les donner � ta fonction?
    Je pourrais, mais au prix de la lisibilit� du code client. Et j�ai parl� de lambdas, mais �a peut aussi �tre le r�sultat de std::bind (mais m�me remarque, on peut le mettre dans un std::function). Au final, ce n�est pas tr�s satisfaisant non plus (je pr�f�re en rester � mes 6 � sp�cialisations � �crites � la main pour l�instant).

  10. #10
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par d�faut
    Pourquoi ne pas mettre la fonction en tant qu'argument template et passer par des tags pour la sp�cialisation (proto<result_type, nb_argument> ou autres) ?

  11. #11
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Citation Envoy� par jo_link_noir Voir le message
    Pourquoi ne pas mettre la fonction en tant qu'argument template et passer par des tags pour la sp�cialisation (proto<result_type, nb_argument> ou autres) ?
    Peux-tu d�tailler ? Je ne suis pas s�r de voir o� tu veux en venir.

  12. #12
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Hello !

    Il est possible de faire cela, mais il faut ruser un peu en exploitant le fait qu'une lambda est un type qui poss�de un op�rateur (). Voici un exemple (il y a plusieurs mani�re de s'y prendre) :

    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
    #include <functional>
    #include <iostream>
     
    template <typename Function> struct function_traits ;
     
    template <typename ClassType, typename ReturnType, typename... Args>
    struct function_traits<ReturnType(ClassType::*)(Args...) const> {
      using function = const std::function<ReturnType(Args...)>;
    };
     
    template<typename... args>
    int func(std::function<int(args...)> f)
    {
         return sizeof...(args);
    }
     
    template<typename T>
    typename std::enable_if<std::is_function<T>::value, int>::type
    func2(T const& f)
    {
         return func(std::function<T>(f));
    }
     
    template<typename T>
    typename std::enable_if<!std::is_function<T>::value, int>::type
    func2(T const& f)
    {
         return func( static_cast<typename function_traits<decltype(&T::operator())>::function>(f));
    }
     
    int f2(int a, int b, int c) { return a+b+c; }
     
    int main() {
      std::cout << func2(f2) << "\n";
      std::cout << func2([](int a, int b) { return a+b; }) << "\n";
    }
    Je ne l'ai pas fait dans l'exemple pour aller au plus court en collant � ton use case, mais le plus propre reste de se coder une fonction template to_function qui prend n'importe quoi et sort le std::function qui va bien, en utilisant la m�me technique que ci-dessus. Test� sur gcc 4.7.2 avec succ�s (tu serais pas coinc� sous wheezy par hasard ?).

    Edit : une version r�utilisable.

  13. #13
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par d�faut
    C'est � peu de choses pr�s la m�me id�e. La seule diff�rence est que function_trais servirait plus � cr�er un type prototype<Result(Args...)> pour l'envoyer en premier param�tre de func. Cela �vite d'instancier un objet std::function qui est un peu lourd (v�rification de l�existence d'une fonction, allocation dynamique, etc).

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Oui, je vois, une version g�n�rique avec un type qui repr�sente la signature en somme ? C'est possible en effet, mais vu que l'op utilise un std::function dans tous les cas, c'est pas la peine de trop s'emb�ter .

    Autre remarque : on ne peut pas faire �a avec des bind expressions (r�sultatt de std::bind) car celles-ci peuvent supporter plusieurs surcharges dans une seule expression. De fait, pour pouvoir convertir une bind expression en std::function, il faut explicitement dire quelle surcharge on veut (m�me s'il n'y en a qu'une, h�las).

  15. #15
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    Bon, je commence � entrevoir quelques solutions, merci beaucoup pour vos suggestions !

    tu serais pas coinc� sous wheezy par hasard ?
    �a se voit tant que �a ?

  16. #16
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Citation Envoy� par white_tentacle Voir le message
    �a se voit tant que �a ?
    gcc 4.7.2, c'est grill�. J'ai la m�me de mon c�t� .

  17. #17
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Je pense avoir une piste qui pourrait t'aider.

    L'id�e principale serait de se reposer sur boost::fusion::invoke qui prend en param�tre un foncteur et une s�quence boost.fusion. Ton objectif est (si j'ai bien compris et en simplifiant) d'arriver � une fonction make_ qui � partir d'un foncteur te retourne un foncteur acceptant en entr�e une s�quence d'objet et retournant le foncteur appliqu� � chaque �l�ment de la s�quence transform� ?

    Donc en reprenant fusion::invoke, le foncteur tu l'as. La probl�matique est sur la s�quence boost.fusion, la taille d'une telle s�quence doit �tre fix� � la compilation et les types des �l�ments aussi. En se restreignant aux foncteurs monomoprhique, � un nombre maximal de param�tre et un ensemble de types de donn�es connus, on peut passer outre. Un code pour voir l'id�e est plus clair que de longues phrases :
    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
     
    #include<string>
    #include<utility>
    #include<vector>
     
    #include<boost/fusion/container/vector.hpp>
    #include<boost/fusion/container/generation/make_vector.hpp>
    #include<boost/fusion/functional/invocation/invoke.hpp>
     
    namespace fusion = boost::fusion;
     
    struct A
    {};
     
    struct B
    {};
     
    //Un type intermédiaire pour aller des std::string aux paramètres
    struct sys_init
    {
    	sys_init(const std::string& s)
    		: str(s)
    	{}
     
            //C'est là que tu peux vérifier ce que tu veux avant de construire les objets
    	operator A() const
    	{ return A(); }
    	operator B() const
    	{ return B(); }
     
    private:
    	std::string str;
    };
     
    void foo(A){}
    void bar(B){}
     
    template<class F>
    std::function<void(const std::vector<std::string>&)>
    	make_adapt(F&& fun)
    {
    	return
    		[fun](const std::vector<std::string>& seq)
    		{
                            //Ici appel avec seulement un paramètre, si ca ne correspond ps erreur de compilation
    			fusion::invoke(fun,fusion::make_vector(sys_init(seq[0])));
     
    			//Vers du SFINAE et boost.pp pour tester jusqu'au nombre de paramètre voulu :
    			//call_or_ignore<fusion::vector<sys_init>>(fun,seq);
    			//call_or_ignore<fusion::vector<sys_init,sys_init>>(fun,seq);
    			//...
    		}
    	;
    }
     
    int main()
    {
           //De quoi stocker mes foncteur
    	std::vector<
    		std::function<void(const std::vector<std::string>&)>
    	> seq_fun;
    	seq_fun.reserve(2);
     
            //Une donnée d'entrée à passer à foo et bar
    	std::vector<std::string> seq_s {"a"};
     
    	seq_fun.push_back(make_adapt(foo));
    	seq_fun.push_back(make_adapt(bar));
     
            //Appel
    	seq_fun[0](seq_s);
    	seq_fun[1](seq_s);
    }
    J'ai regard� un peu pour faire le SFINAE, mais il n'est pas si trivial que �a � faire (certains �l�ments de boost supporte mal cette technique). Il faut aussi faire attention lors de l'�criture pour limiter les copies. Je vais continuer de regarder et je reposterais si j'avance un peu plus.

  18. #18
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    @Flob90: je pense que tu as confondu avec ce post.

  19. #19
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    @jblecanard: Non, je me suis pas tromp�. C'est juste que je pr�f�re partir du "pseudo-code" de ce qu'il veut faire, que du probl�me technique de sp�cialisation, j'ai juste pas pris en compte std::map<std::string, ParamDescription> const& paramDescription et utilis� un const std::vector<std::string>& seq � la place d'une std::map<std::string, variant>.

  20. #20
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par d�faut
    En fait, pour la deuxi�me partie (l�appel de la fonction), j�ai test� avec succ�s le template suivant, qui fonctionne avec une array mais aussi un tuple :

    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
     
    template<const int n>
    struct f
    {
        template<typename Array, typename Fun, typename... Args>
        static auto call(Fun fun, Array const& arr, Args... arg) -> decltype(f<n-1>::call(fun, arr, std::get<n-1>(arr), arg...))
        {
            return f<n-1>::call(fun, arr, std::get<n-1>(arr), arg...);
        }
    };
     
    template<>
    struct f<0>
    {
        template<typename Array, typename Fun, typename... Args>
        static auto call(Fun fun, Array /*arr*/, Args... arg) -> decltype(fun(arg...))
        {
            return fun(arg...);
        }
    };
    Simple et efficace. En cumulant �a et le make_function, je dois pouvoir m�en sortir en sp�cialisant tr�s peu de code (juste le make_function, en fait).

+ R�pondre � la discussion
Cette discussion est r�solue.
Page 1 sur 2 12 Derni�reDerni�re

Discussions similaires

  1. R�ponses: 4
    Dernier message: 30/05/2011, 19h38
  2. R�ponses: 2
    Dernier message: 10/01/2009, 13h38
  3. Probl�me de class template et std::map
    Par bathof dans le forum Langage
    R�ponses: 2
    Dernier message: 31/07/2007, 22h18
  4. template et std::vector
    Par themadmax dans le forum Langage
    R�ponses: 9
    Dernier message: 26/07/2006, 10h41

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