J'étais certain qu'il fallait le demander avant mais je ne l'ai pas trouvé.

J'ai une classe encapsulant std::string, à l'intérieur je veux surcharger les deux transtypages en char* et l'opérateur d'accès[].

class String
{
public :
    String(const char* s) { m_str = s; }
    const char* str() const  { return m_str.c_str(); }
    char* str()  {  return &m_str[0]; }
    char operator[](size_t pos) const { return m_str[pos]; }
    char& operator[](size_t pos) { return m_str[pos]; }
    operator const char*() const { return str(); }  // cast operator
    operator char*() { return str(); }  // cast operator
protected:
    std::string m_str;
};

void main()
{
    String s = "1234";
    if(s[0] != '1')   //'String::operator []': 4 overloads have similar conversions !!!!!
        std::cout << "Error" << endl;
}

Le problème est maintenant bien sûr que lorsque j'essaie d'utiliser String [], je reçois l'erreur "4 surcharges ont des conversions similaires", le compilateur ne peut pas décider quoi faire :
1) utiliser directement l'opérateur de surcharge[]
2) convertissez d'abord en char * en utilisant operator() puis operator[] sur le tableau char*

Existe-t-il un moyen de conserver les deux opérateurs ? Pour de nombreuses fonctions, etc. acceptant char* et const char* pour utiliser operstor() de String mais dans tous les autres cas directement l'opérateur[] (ne pas essayer de convertir en carboniser*).

Je suppose que la réponse à cette question est probablement Non, et c'est pourquoi dans std::string il n'y a pas d'opérateur de transtypage char*, mais peut-être que quelque chose a changé dans le C++ plus récent normes.

EDIT : je peux compiler ce qui précède avec GCC mais cela échoue avec VS (x86). Erreur C2666 'String::operator []' : 4 surcharges ont des conversions similaires

1
Baj Mile 21 nov. 2019 à 23:20

1 réponse

Meilleure réponse

Compilez toujours votre code avec les avertissements activés, pour gcc et clang l'option de ligne de commande est -Wall -Wextra -Werror. Les avertissements vous diront que operator[] doit renvoyer une valeur.


Dans l'expression s[0] en mode 32 bits, les compilateurs clang et msvc considèrent la conversion standard de l'index int en unsigned (32 -bit size_t) doit être du même rang que la conversion définie par l'utilisateur de String en char*. Voir les messages d'erreur du compilateur ici. Ces dernières conversions étant une conversion définie par l'utilisateur ont un rang pire que n'importe quelle conversion standard, mais les compilateurs ne peuvent pas résoudre ce lien. Je ne sais pas exactement quelle règle standard s'applique ici.

Un correctif consiste à ajouter une autre surcharge de operator[] qui accepte un index signé ptrdiff_t :

char operator[](ptrdiff_t pos) const { return m_str[pos]; }
char& operator[](ptrdiff_t pos) { return m_str[pos]; }
1
Maxim Egorushkin 22 nov. 2019 à 12:46