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 :

templates: tuple de foncteurs et operateurs ()


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    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 templates: tuple de foncteurs et operateurs ()
    Depuis plusieurs mois, je travaille sur une bibliothèque de composition de fonctions mathématiques et plus si affinités.

    Et finalement, je rencontre un problème de construction template.

    Le besoin de base est le suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <des choses, typename F...>
    struct tied_functors {
    std::tuple<F...> functors;
     
    using signature = std::tuple < std::common_type<le I° argument de chaque F>... >;
     
    auto operator() (Args...) const {
        static_assert( Args... compatible avec signature partagée, "appel impossible" );
        return std::make_tuple( functors[](Args...)... );
    }
    };
    Je passe sous le capot la partie qui permet d'accéder à tous les foncteurs (ca implique std::get<> et std::integer_sequence)

    Mon soucis concret, c'est qu'actuellement, ma détection de signature ne fonctionne pas avec les références (non const).

    Or common_type est défini pour retirer les références (et cv-qualifiers)
    du coup, si j'ai deux foncteurs de type iterator double(Bidule&) et int(Bidule&), j'ai bien comme signature effective std::tuple<double, int>(Bidule).

    Ce qui ne fonctionne pas, car le bidule transmis en référence non constante est une temporaire.

    Ma question s'articule donc ainsi:
    sachant deux foncteurs f(A) et g(B), quel type C d'argument dois-je utiliser pour le transmettre à f et g?

    Je n'arrive pas à me dépatouiller dans la norme…

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Salut,

    je sais pas si c'est directement utile ou pas, mais ça m'a rappelé cette présentation de Joel et Edouard (il me semble) lors d'un meetup y'a ~2ans : https://github.com/edouarda/brigand/wiki
    Peut-être que tu y trouveras ton bonheur ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    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
    Avec brigand on peut faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<class T, class U>
    using ternary_conditional_t = decltype(1 ? std::declval<T>() : std::declval<U>());
     
    template<class T, class... Ts>
    using common_type = brigand::fold<
      brigand::list<Ts...>,
      T,
      brigand::bind<ternary_conditional_t, brigand::_1, brigand::_2>
    >;
    Mais pour garder une référence, il faut que tous les types soient identiques.

  4. #4
    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
    Ca pourra m'être utile, en effet, mais ca n'est pas mon blocage du moment.

    je n'arrive pas à trouver tous les cas valides, et ceux qui ne le sont pas, pour lier deux foncteurs (ou plus, d'ailleurs).

    Si je résume mon problème en supprimant la couche variadique, et en limitant mes foncteurs à un argument.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <typename R1, typename A1, typename R2, typename A2>
    struct unary_functor_pair {
        using F1 = std::function<R1(A1)>;
        using F2 = std::function<R2(A2)>;
     
        using arg_type = ???
     
        auto operator() (arg_type arg) { return std::make_tuple( f1(arg), f2(arg) ); }
     
    private:
        F1 f1;
        F2 f2;
    };
    note: mon code réel utilise directement le type réel de F1 et F2, pas une std::function, mais ca ne change pas le problème présent

    pour A1 = T &, A2=T const&, il faut nécessairement que arg_type soit T &, car ca ne peut pas être un T ou un T const&.
    pour [c]T[c] et T const&, j'ai le choix entre T et T const&, et ce second choix me semble meilleur.

    mais pour toutes les combinaisons de {/?/&&} et {/const/const volatile/volatile}, je ne sais pas vraiment.
    Et vient aussi la question de l'utilisation de std::forward.

    plus traitre, que faire pour Vehicule&, Camion const&. A priori, Camion&Edit: croisé avec ta réponse, jo_link_noir.
    Ca m'a l'air une bonne piste, mais ca marchera aussi avec l'héritage?
    Et les conversions simples, genre int const&, long const&.
    J'ai du mal à voir ce qui est sensé être valable de ce qui est une fausse idée que je me fais.

  5. #5
    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
    As-tu vraiment besoin de arg_type/signature ? Parce qu'il est plus simple de vérifier si un type est valide pour un appel de fonction (std::is_callable) que de trouver le type commun. D'ailleurs, il peut ne pas exister de type commun déductible (paramètre class C : A,B{} avec f(A) et g(B). C est bon, mais aucun commun entre A et B).

    Ca m'a l'air une bonne piste, mais ca marchera aussi avec l'héritage?
    Et les conversions simples, genre int const&, long const&.
    Non, le type est différent alors (grosso modo) le compilateur fait un decay<T>/decay<U> selon qui est convertible en quoi.

  6. #6
    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
    Hum, en effet, c'est une judicieuse remarque. Par contre, std::is_callable est disponible en C++17 uniquement. à voir si je peux le reproduire en C++14, voire 11.

    Donc, je vais voir réviser mon système de restriction.
    De même, si une référence constante et référence non constante peuvent toutes deux être alimentée par une référence modifiante, l'ordre des opérations n'aura pas forcément un effet stable.

    Je vais continuer à spécifier mes intentions.

    Ou alors, je cherche fabrique un algo du genre invoke/apply et je le compose sur un tuple de functeur.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par ternel Voir le message
    Hum, en effet, c'est une judicieuse remarque. Par contre, std::is_callable est disponible en C++17 uniquement. à voir si je peux le reproduire en C++14, voire 11.

    Donc, je vais voir réviser mon système de restriction.
    De même, si une référence constante et référence non constante peuvent toutes deux être alimentée par une référence modifiante, l'ordre des opérations n'aura pas forcément un effet stable.

    Je vais continuer à spécifier mes intentions.

    Ou alors, je cherche fabrique un algo du genre invoke/apply et je le compose sur un tuple de functeur.
    A défaut, tu pourrais peut être envisager de tester la présence de l'opérateur () à l'aide de std::is_member_function_pointer, vu que, l'un dans l'autre, tu travailleras essentiellement avec des foncteurs... Non

    (je me demande d'ailleurs si std::is_callable ne fera pas purement et simplement appel à std::is_member_function_pointer en interne )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. template et heritage de l'operateur =
    Par yan dans le forum Langage
    Réponses: 2
    Dernier message: 25/02/2011, 09h22
  2. Réponses: 6
    Dernier message: 12/07/2007, 18h18
  3. Foncteur, classes templates et héritage
    Par Floréal dans le forum C++
    Réponses: 8
    Dernier message: 17/06/2007, 21h56
  4. [Template] Surcharge operateur
    Par juls64 dans le forum C++
    Réponses: 7
    Dernier message: 04/05/2007, 19h35
  5. [Débutant]Foncteur et operator() template
    Par Sub dans le forum Langage
    Réponses: 14
    Dernier message: 27/03/2007, 13h51

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