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 :

[POO] overload en changeant un argument par une sous-classe du type precedent


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 24
    Points : 21
    Points
    21
    Par défaut [POO] overload en changeant un argument par une sous-classe du type precedent
    Impossible de trouver de la lecture sur le même cas que ce qui me bloque, donc voilà mon probleme :

    J'ai les classes suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<class T> class Idx {...}
    template<class T> class spIdx : public Idx<T> {...}
    puis les fonctions suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    void myfunc(Idx<double> &i1, Idx<double> &i2, Idx<double> &i3);
    template<class T> void myfunc(spIdx<T> &i1, Idx<T> &i2, Idx<T> &i3);
    Enfin, je fais l'appel suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    spIdx<double> sptest(0, 4, 4);
    Idx<double> x(4), y(4);
    myfunc(sptest, x, y);
    J'obtiens alors l'erreur suivante :
    " erreur: call of overloaded «myfunc(ebl::spIdx<double>&, ebl::Idx<double>&, ebl::Idx<double>&)» is ambiguous
    note: candidats sont: void myfunc(ebl::spIdx<T>&, ebl::Idx<T>&, ebl::Idx<T>&) [with T = double]
    note: void myfunc(ebl::Idx<double>&, ebl::Idx<double>&, ebl::Idx<double>&) "

    Comment régler ce problème ? et pourquoi le compilateur ne choisit-il pas la version dont la signature (bien que templatée) correspond (appel à la sous-classe spIdx) ?
    J'ai essayé de caster la variable dans son propre type lors de l'appel à la fonction (ie idx_m2dotm1(static_cast<spIdx<double>&>(sptest), x, y);

    Bien evidemment je ne veux pas changer le nom des fonctions, le but étant que l'utilisateur n'aie pas à se soucier de la classe utilisée...

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Du point de vue des opération à faire pour convertir les arguments de la fonction, la version templatée est meilleure que la non templatée. Mais la non templatée est aussi possible, et en tant que non templatée, elle aurait tendance à être préférée. D'où l'ambiguïté (d'ailleurs, avec un oeil naïf, j'aurais crus que c'était la non templatée qui serait prise, alors que tu pensais que ce serait l'autre... C'est donc une bonne chose que le compilateur refuse de compiler, non ?)

    La solution ? Il y en a peut-être d'autres à base de SNIFAE, mais ce qui me vient en tête en premier est de donner au compilateur une fonction qui soit clairement meilleure que ces deux là, et il la prendra sans hésiter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void myfunc(spIdx<double> &i1, Idx<double> &i2, Idx<double> &i3);
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 24
    Points : 21
    Points
    21
    Par défaut
    Ca marche effectivement, mais... j'ai quand même du mal à comprendre pourquoi les 2 opérations sont considérées "du même niveau" par le compilateur...
    Bref, cas résolu

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Les règles précises de surcharge sont assez complexes. Pour déterminer si une fonction est meilleur qu'une autre :
    Citation Envoyé par Le standard 13.3.3
    Define ICSi(F) as follows:
    — if F is a static member function, ICS1(F) is defined such that ICS1(F) is neither better nor worse than ICS1(G) for any function G, and, symmetrically, ICS1(G) is neither better nor worse than ICS1(F)122);
    otherwise,
    — let ICSi(F) denote the implicit conversion sequence that converts the ith argument in the list to the type of the ith parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.
    Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
    — for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
    — F1 is a nontemplate function and F2 is a template function specialization, or, if not that,
    — F1 and F2 are template functions, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.5.2, or, if not that,
    — the context is an initialization by userdefined conversion (see 8.5, 13.3.1.5) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized)
    is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type. [Example:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct A {
    A();
    operator int();
    operator double();
    } a;
    int i = a; // a.operator int() followed by no conversion
    // is better than a.operator double() followed by
    // a conversion to int
    float x = a; // ambiguous: both possibilities require conversions,
    // and neither is better than the other
    —end example]
    2 If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is illformed123).
    Suivent les règles définissant les séquences de conversion...

    C'est expliqué en détails dans "C++ templates, the complete guide" de Jossutis et Vandervoorde.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Les versions de g++ que j'ai essayé, ainsi que Sun CC préfèrent bien la version template. C'est avec quel compilateur que tu as essayé?
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 24
    Points : 21
    Points
    21
    Par défaut
    g++ 4.2.3 pourtant, via eclipse IDE sous ubuntu...

  7. #7
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par xenosender Voir le message
    g++ 4.2.3 pourtant, via eclipse IDE sous ubuntu...
    On peut voir ton code complet présentant le problème?

    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
    [~/src]$ cat xenosender.cpp
    #include <iostream>
    #include <ostream>
     
    template<class T> class Idx
    {
    public:
        Idx(int) {}
    };
     
    template<class T> class spIdx : public Idx<T>
    {
    public:
        spIdx(int a, int, int) : Idx<T>(a) {}
    };
     
    void myfunc(Idx<double> &i1, Idx<double> &i2, Idx<double> &i3)
    {
        std::cout << "myfunc\n";
    }
     
    template<class T> void myfunc(spIdx<T> &i1, Idx<T> &i2, Idx<T> &i3)
    {
        std::cout << "myfunc<T>\n";
    }
     
    int main()
    {
        spIdx<double> sptest(0, 4, 4);
        Idx<double> x(4), y(4), z(4);
        myfunc(sptest, x, y);
        myfunc(x, y, z);
    }
    [~/src]$ g++-3.2 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ g++-3.3 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ g++-3.4 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ g++-4.0 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ g++-4.1 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ g++-4.2 --version
    g++-4.2 (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
    Copyright (C) 2007 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     
    [~/src]$ g++-4.2 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ g++-4.3 -Wall -std=c++98 -pedantic-errors xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    [~/src]$ CC xenosender.cpp
    [~/src]$ ./a.out
    myfunc<T>
    myfunc
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 24
    Points : 21
    Points
    21
    Par défaut
    J'ai peur que ca ne soit un peu long malheureusement, les classes et fonctions etant réparties sur plusieurs fichiers et projets différents...

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 19/05/2007, 11h04
  2. Contrôle d'une fenêtre par une autre classe
    Par SuperWeight dans le forum Windows
    Réponses: 4
    Dernier message: 19/04/2007, 17h01
  3. Réponses: 3
    Dernier message: 30/03/2007, 11h38
  4. Réponses: 3
    Dernier message: 07/04/2006, 21h35
  5. Réponses: 3
    Dernier message: 18/05/2003, 01h16

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