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 :

Templates variadiques et déduction du type de retour.


Sujet :

C++

  1. #1
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut Templates variadiques et déduction du type de retour.
    Bonjour, avec c++0x de gcc 4.5, les MesArgs... ne peuvent êtres capturés dans les lambda.
    Pour résoudre ce problème, je les mes dans un tuple avant le lambda et je capture le tuple.
    Cependant, quand il faut appeler std::bind(Func, MesArgs...), j'ai quelques problèmes.

    J'ai donc fais une fonction qui extrait le tuple et qui renvoie std::bind(Func, MesArgs...);
    Il semblerait que le compilateur n'arrive pas à déterminer implicitement le type de retour de ma fonction Bind(Func, tuple);
    Est-ce une erreur de ma part ? Un défaut du compilateur ?

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::tuple<ArgsParam...> tuple(param...);
    return std::function<void(void*)>([&retour, function, tuple](void*Arguments)
    {
        auto GodFunc=Binding<Fc,ArgsParam...>::MakeBindingObject(static_cast<Fc>(function), tuple);
        /*Autres Choses*/
    });
    Et,


    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<unsigned int N, typename Fc, typename ...Args>
    struct ExtractTuple
    {
        template<typename R, typename T, typename ...Finis>
        inline static R Extract(Fc Func, const std::tuple<Args...>& t, T Obj, Finis...Extracted)
        {
            return ExtractTuple<N-1, Fc, Args...>::Extract
            (static_cast<Fc>(Func), t, std::get<N-1>(t), Extracted...);
        }
    };
     
    template<typename Fc,  typename ...Args>
    struct ExtractTuple<0u, Fc,  Args...>
    {
        template<typename R, typename ...Finis>
        inline static R Extract(Fc Func, const std::tuple<Args...>& t, Finis... Extracted)
        {
            return std::bind(Func, Extracted...);
        }
    };
     
    template<unsigned int N, typename Fc>
    struct ExtractFirst
    {
        template<typename R,typename ...Args>
        inline static R Extract(Fc Func, const std::tuple<Args...>& t)
        {
            return ExtractTuple<N-1, Fc, Args...>::Extract
            (static_cast<Fc>(Func), t, std::get<N-1>(t));
        }
    };
     
     
    template<typename Fc,typename ...Args>
    struct Binding
    {
        template<typename R>
        inline static R MakeBindingObject(Fc Func, const std::tuple<Args...>& t)
        {
            return ExtractFirst<sizeof...(Args), Fc>::Extract(static_cast<Fc>(Func), t);
        }
    };
    Voici l'erreur indiquée par le compilateur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    instantiated from 'static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = sf::GUI::Evenement<Args>::MakeCallbackWithReturn(R&, Fc, ArgsParam ...) [with R = double, Fc = double (*)(int), ArgsParam = {int}, Args = {double}]::<lambda(void*)>, _ArgTypes = {void*}]'|
    instantiated from 'std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = sf::GUI::Evenement<Args>::MakeCallbackWithReturn(R&, Fc, ArgsParam ...) [with R = double, Fc = double (*)(int), ArgsParam = {int}, Args = {double}]::<lambda(void*)>, _Res = void, _ArgTypes = {void*}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Usel|
    instantiated from 'static std::function<void(void*)> sf::GUI::Evenement<Args>::MakeCallbackWithReturn(R&, Fc, ArgsParam ...) [with R = double, Fc = double (*)(int), ArgsParam = {int}, Args = {double}]'|
    instantiated from here|
    error: no matching function for call to 'Binding<double (*)(int), int>::MakeBindingObject(double (*)(int), const std::tuple<int>&)'|
    Après quelques tests, il semblerait que l'erreur soit dû au fait que je ne précise pas explicitement le type de retour de MakeBindingObject.

    Merci d'avance.

  2. #2
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    J'ai trouvé une solution (en fouillant dans le header functionnal).
    Il faut bel et bien explicité le type de retour (semblerait que gcc manque de déduction...).
    Cependant, ce type de retour peut être déterminer à partir des typedefs suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    typedef std::_Maybe_wrap_member_pointer<Fc> __maybe_type;
    typedef typename __maybe_type::type __functor_type;
    typedef std::_Bind<__functor_type(Args...)> __result_type;
    Voici le code complet, qui bind une fonction avec 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
    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
    template<unsigned int N, typename Fc, typename R, typename ...Args>
    struct ExtractTuple
    {
        template<typename ...Finis>
        inline static R Extract(Fc Func, const std::tuple<Args...>& t, Finis...Extracted)
        {
            return ExtractTuple<N-1, Fc, R, Args...>::Extract
            (static_cast<Fc>(Func), t, std::get<N-1>(t), Extracted...);
        }
    };
     
    template<typename Fc, typename R,  typename ...Args>
    struct ExtractTuple<0u, Fc,R,  Args...>
    {
        template<typename ...Finis>
        inline static R Extract(Fc Func, const std::tuple<Args...>& t, Finis... Extracted)
        {
            return std::bind(Func, Extracted...);
        }
    };
     
    template<unsigned int N, typename R,typename Fc>
    struct ExtractFirst
    {
        template<typename ...Args>
        inline static R Extract(Fc Func, const std::tuple<Args...>& t)
        {
            return ExtractTuple<N-1, Fc, R,Args...>::Extract
            (static_cast<Fc>(Func), t, std::get<N-1>(t));
        }
    };
     
     
    template<typename Fc,typename ...Args>
    struct Binding
    {
        typedef std::_Maybe_wrap_member_pointer<Fc> __maybe_type;
        typedef typename __maybe_type::type __functor_type;
        typedef std::_Bind<__functor_type(Args...)> __result_type;
     
        inline static __result_type MakeBindingObject(Fc Func, const std::tuple<Args...>& t)
        {
            return ExtractFirst<sizeof...(Args), __result_type,Fc>::Extract(static_cast<Fc>(Func), t);
        }
    };

  3. #3
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    J'ai maintenant un autre problème :

    std::bind retourne un foncteur qui possède un operateur ().
    Cependant, cet operator nécessite au moins autant d'arguments et chacun du bon type qu'il y a eut de placeholders.
    Comment déterminer le nombre d'arguments et leur type ?
    (Je n'ai pas réussit à trouver dans functionnal).
    Il doit y avoir un typedef ou autre quelque part. Quelqu'un a une idée ?

    [EDIT]
    Voici le code plus précisément :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    std::function<void(void*)> Evenement<Args...>::MakeCallbackWithReturn(R& retour,Fc function, ArgsParam... param)
        {
            std::tuple<ArgsParam...> tuple(param...);
            return std::function<void(void*)>([&retour, function, tuple](void*Arguments)
            {
                auto GodFunc=Binding<Fc,ArgsParam...>::MakeBindingObject(static_cast<Fc>(function), tuple);
                if(Arguments==NULL)
                    retour=GodFunc();
                else
                    retour=Binding<typename Binding<Fc,ArgsParam...>::ResultFunctorType,Args...>::MakeBindingObject(GodFunc, (static_cast<Evenement<Args...>*>(Arguments))->GetArgs())();
            });
        }
    Le problème :

    Le compilateur va essayer de passer dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if(Arguments==NULL)
         retour=GodFunc();
    Même si, il ne devrait jamais y passer si l'opérateur () de GodFunc demande des arguments. Comment faire pour éviter ce problème ?

    De plus, pour éviter d'avoir une flopée de instanciated here, j'aimerais pouvoir faire un static_assert(arguments_are_valid, "On ne peut faire correspondre vos arguments avec ceux émis : vous avez un std::placeholder::_7 alors que le tuple du void* n'a que 6 cases.");

    Voila a quoi cela servirait de récupérer le nombre et le type des arguments attendus.

Discussions similaires

  1. Réponses: 4
    Dernier message: 08/08/2013, 14h34
  2. Template et fonction amie / type de retour inconnu
    Par Armas dans le forum Débuter
    Réponses: 13
    Dernier message: 24/04/2013, 15h17
  3. Réponses: 12
    Dernier message: 02/12/2010, 11h36
  4. [template] arguments et type de retour
    Par drKzs dans le forum C++
    Réponses: 10
    Dernier message: 24/08/2008, 16h41
  5. type de retour de fonction template
    Par k1000 dans le forum Langage
    Réponses: 5
    Dernier message: 21/04/2008, 11h41

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