• [^] # Re: Indice

    Posté par . En réponse au message Bizarrerie opérateur ternaire (?:). Évalué à 2. Dernière modification le 11 juin 2020 à 11:33.

    L'indice de Cyril t'indique la bonne direction.

    J'ai refait ton truc avec un constructeur de copie et en virant les std::flush et les std::endl, parce que d'une part, dans endl il y a déjà un flush, et d'autre part, tu t'intéresses à la sortie standard du programme une fois terminé, alors tu n'as pas besoin de faire un flush à chaque évènement quantique. Du coup c'est moins lourd à lire.

    #include <iostream>
    class my_class {
     char c_;
    public:
     my_class(char c) {
     c_ = c;
     std::cout << "Ctor: " << c_ << '\n';
     }
     my_class(const my_class & rhs) : c_(rhs.c_) {
     std::cout << "Cpy: " << c_ << '\n';
     }
     ~my_class() {
     std::cout << "Dtor: " << c_ << '\n';
     }
    };
    #define M(e)\
     std::cout << "\ntrue ? " << #e << '\n';\
     (true ? e)
    int main() {
     my_class A('A'), B('B');
     M( A : B );
     M( A : my_class('C') );
     M( my_class('D') : A );
     M( my_class('E') : my_class('F') );
     std::cout << "\nEnd main()\n";
    }

    Comme l'indiquait Cyril, une copie est effectuée quand tu invoques true ? A : my_class('C') et pas dans les autres cas. Cette copie est nécessaire pour que les deux arguments de l'opérateur ternaire soient de même type (my_class).
    * Dans la ligne précédente, les deux arguments sont déjà du même type (my_class &) et aucune conversion n'est nécessaire ;
    * Dans la ligne suivante, une conversion serait nécessaire, mais elle n'a pas lieu parce qu'elle est codée dans la branche false de l'opérateur ternaire ;
    * Dans le dernier cas, les deux arguments sont de type (my_class) et aucune conversion n'est nécessaire.

    Un collègue sympa a réécrit le code avec des template pour mettre en évidence les types utilisés :

    #include <iostream>
    class my_class {
     char c_;
    public:
     my_class(char c) {
     c_ = c;
     std::cout << "Ctor: " << c_ << '\n';
     }
     my_class(const my_class & rhs) : c_(rhs.c_) {
     std::cout << "Cpy: " << c_ << '\n';
     }
     ~my_class() {
     std::cout << "Dtor: " << c_ << '\n';
     }
    };
    template <typename> char const* type();
    template <> char const* type<my_class&>() { return "my_class&"; }
    template <> char const* type<my_class const&>() { return "my_class const&"; }
    template <> char const* type<my_class>() { return "my_class"; }
    #define M(e)\
     std::cout << "\ntrue ? " << #e << '\n';\
     std::cout << "type=" << type<decltype(true? e)>() << "\n"; \
     (true ? e)
    int main() {
     my_class A('A'), B('B');
     M( A : B );
     M( A : my_class('C') );
     M( my_class('D') : A );
     M( my_class('E') : my_class('F') );
     std::cout << "\nEnd main()\n";
    }