web-dev-qa-db-fra.com

Pourquoi différentes fonctions de conversion pour int et const int sont-elles autorisées?

Pourquoi les éléments suivants peuvent-ils être compilés en C++?

#include<iostream>
using namespace std;

class mytest
{
public:    
    operator int()
    {
        return 10;
    }

    operator  const int()
    {
        return 5;
    }
};

int main()
{
    mytest mt;
    //int x = mt;    //ERROR ambigious 
    //const int x = mt; //ERROR ambigious
}

Pourquoi est-il logique de permettre la compilation de différentes versions (basées sur la constance) de l'opérateur de conversion alors que leur utilisation entraîne toujours une ambiguïté?

Quelqu'un peut-il clarifier ce qui me manque ici?

25
code707

J'en arrive à la conclusion qu'il n'est pas explicitement autorisé d'écrire des opérateurs de conversation qui ne diffèrent que par la constance de leur valeur de retour. Il est trop cher pour le processus de compilation de l'interdire explicitement.

N'oubliez pas que les fonctions (membres) ne diffèrent que par leur type de retour

class mytest
{
    int f();
    const int f();
};

sont interdits:

erreur: ‘const int mytest :: f ()’ ne peut pas être surchargé

C'est juste que les opérateurs de conversion commencent par operator qui fait la différence.

1
Wolf

Pour la conversion, ils sont ambigus; mais vous pouvez les appeler explicitement. par exemple.

int x = mt.operator int();
const int x = mt.operator const int();
18
songyuanyao

Je crois qu'au sens strict, même si cela n'a pas vraiment de sens pour const, c'est légitime.

Il existe une différence entre une déclaration de fonction et un type de fonction, et ils n'ont pas les mêmes contraintes.

La fonction déclarations ne peut pas différer uniquement par leur type de retour ou (depuis C++ 17) la spécification d'exception. Cependant, rien de tel n'est dit sur la fonction type (à ma connaissance).

La classe [class.conv.fct] standard décrit les fonctions de conversion comme ayant telle ou telle forme (trois alternatives répertoriées), qui ne ressemblent pas toutes à des déclarations de fonctions normales, en particulier, elles n'ont évidemment aucun type de retour.

Il indique, que le type de fonction est "fonction ne prenant aucun paramètre renvoyant conversion-type-id", mais nulle part il n'est mentionné que la fonction de conversion déclarations avoir une telle chose comme un type de retour. Au contraire, les trois formes alternatives listées n'ont très clairement pas de type de retour.

Puisque les fonctions de conversion n'ont pas ont un type de retour (... dans leur déclaration), il ne peut pas entrer en conflit. Donc, je suppose que, dans le sens le plus strict et le plus pédant, c'est même un peu "légal", que cela ait du sens ou non.

Si vous y pensez, alors en quelque sorte doit être légal aussi. Une classe peut très bien avoir plus d'une fonction de conversion en différentes choses (pas seulement en se différenciant par const). Un tel code existe, et il est parfois très logique de procéder ainsi.
Vous pouvez par exemple avoir une classe File qui se convertit en string (le nom de fichier) ou en handle_t (le descripteur du système d'exploitation) au cas où vous voudriez utiliser une fonction spécifique au système d'exploitation ou exotique que votre classe wrapper ne prend pas directement en charge (pensez writev, tee ou epoll?) C'est certainement quelque chose que vous attendez de travailler!
Si, toutefois, nous considérions les fonctions de conversion comme des "fonctions simples", elles ne différeraient que par leur type de retour, ce qui rendrait les déclarations illégales. Alors ... ça ne marcherait pas.

5
Damon

pourquoi est-il logique de permettre une version différente (basée sur la constance) de l'opérateur de conversion (à compiler) alors que leur utilisation entraîne toujours une ambiguïté;

Cela n'a généralement aucun sens (en dehors des cas d'utilisation très artificiels) et un compilateur pourrait vous en avertir:

prog.cc:12:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     operator  const int()
                         ^
4
Jodocus