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 :

Constructeur variadic template


Sujet :

Langage C++

  1. #1
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut Constructeur variadic template
    Bonjour !
    Je cherche à avoir un constructeur variadic template !
    Voici un ideone qui fourni un code qui ne compile pas.

    http://ideone.com/ugYmE9

    Probleme:
    Lors de la construction de D, le constructeur utilisé par C est appelé, au lieu du variadic (il a trois argument, et pense donc que le string est un directory::ptr.
    Donc l'énoncé est simple, comment faire pour resoudre ceci ?

    merci

    nico

  2. #2
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Bonsoir,

    À la ligne 40 il manque la transmission du paramètre 'separator' .

    Il me semble aussi que le passage d'un boolean (bool D) pour savoir s'il reste des éléments est inutile. Le nombre de paramètre dans la spécification est suffisant.

    Bonne nuit.

  3. #3
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut
    En effet, mais cela ne solutionne en rien le probleme malheureusement ^^

    >> http://ideone.com/YS7uyr

    On voit bien, B , C , D sont interpretés avec le constructeur variadic, alors que jai bien 4 constructeurs differents, qui correspondent à A, B, C ,D !

    Comment solutionner ceci ?

  4. #4
    En attente de confirmation mail

    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 : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    Tu as un typedef ptr dans la classe any sur std::shared_ptr<any>, donc dans any ton constructeur avec ptr n'utilise pas le même type ptr que le constructeur avec ptr dans directory.

    Pour faire simple, ton problème se résume à :
    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
     
    #include<memory>
    #include<iostream>
     
    struct A {};
    struct B : A {};
     
    void foo(std::shared_ptr<A>)
    { std::cout << 0; }
    template<class T>
    void foo(const T&)
    { std::cout << 1; }
     
    int main()
    {
        std::shared_ptr<B> p;
        foo(p);
    }
    Lors de l'appel, la déclaration template instancie la fonction avec T=shared_ptr<B>. Ainsi lors de la résolution, c'est elle qui est préféré à la première.

  5. #5
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Il y a le même problème avec directory qui attend des std::string et qui reçoit un tableau de char.

    Ne serais-ce pas plus simple de virer les constructeur variadic et passer par une fonction qui crée le chemin (fonction qui sera variadic) ?
    Avec l'implémentation actuelle, tu vas te prendre la tête pour ajouter les variables 'parent' et 'recursive' dans le constructeur variadic.

  6. #6
    Membre habitué
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Points : 176
    Points
    176
    Par défaut
    Salut. Il doit y avoir d'autres erreurs, parce que même quand tu ne laisses que le constructeur variadic de directory et que tu n'essayes que de construire D, tu as des messages d'erreurs à rallonge.

    Je n'ai pas le temps de me plonger dans ton programme pour faire des tests, mais si tu essayes le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <type_traits>
    #include <iostream>
    #include <string>
    void f(const bool& b) {std::cout<<"void f(const bool& b)"<<std::endl;}
    void f(const std::string& str) {std::cout<<"void f(const std::string& str)"<<std::endl;}
    template <typename... Args> void f(const Args&... args) {std::cout<<"void f(const Args&... args)"<<std::endl;}
    int main()
    {
        f(true);
        f(std::string("Hello"));
        f("Hello");
        f(0);
    }
    ça produit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(const bool& b)
    void f(const std::string& str)
    void f(const Args&... args)
    void f(const Args&... args)
    Donc dès que les types ne matchent pas exactement les constructeurs non-variadic, c'est le variadic qui est appelé. En l'occurence, si je passe une chaine de caractère, elle n'est pas convertie implicitement en string et c'est le variadic qui est appelé.

    Alors comment ne brancher sur le variadic que quand les types ne sont pas convertibles vers les types spécifiés dans les constructeurs non-variadic, ou en d'autres mots, comment obtenir ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(const bool& b)
    void f(const std::string& str)
    void f(const std::string& str)
    void f(const bool& b)
    En fait c'est assez simple avec les type traits. Je templatifie (en supposant que le verbe templatifier existe...) tous les constructeurs pour qu'ils soient sur un pied d'égalité et je les bloque manuellement via de la SFINAE à base d'enable_if:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <type_traits>
    #include <iostream>
    #include <string>
    template <typename Bool, class = typename std::enable_if<std::is_fundamental<Bool>::value>::type> void f(const Bool& b) {std::cout<<"void f(const bool& b)"<<std::endl;}
    template <typename String, class = typename std::enable_if<std::is_convertible<String, std::string>::value>::type, class = void> void f(const String& str) {std::cout<<"void f(const std::string& str)"<<std::endl;}
    template <typename... Args> void f(const Args&... args) {std::cout<<"void f(const Args&... args)"<<std::endl;}
    int main()
    {
        f(true);
        f(std::string("Hello"));
        f("Hello");
        f(0);
    }
    Et le tour est joué!

    Dis moi si ça t'aide à t'en sortir.

Discussions similaires

  1. C++ 0x variadic template
    Par victor_gasgas dans le forum Langage
    Réponses: 6
    Dernier message: 21/09/2010, 07h26
  2. Constructeurs et templates
    Par kain_tn dans le forum C++
    Réponses: 7
    Dernier message: 05/08/2009, 11h56
  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