2014-09-23 9 views
30

Der folgende Code wird aufgrund der impliziten Konvertierung für char kompiliert. Ich bin mir nicht sicher warum, denn die einzige implizite Konvertierung, die ich erwarten würde (und von der ich erwarte, dass sie scheitert), ist von char const* bis size_t.C++ unerwartete implict Konvertierung

#include <cstddef> 

struct foo 
{ 
    int operator[](size_t i) const { return 1; } 
    operator char() const { return 'a'; } 
}; 

int main() 
{ 
    foo f; 
    f["hello"]; // compilation error desired here 
} 

Was ist die implizite Konvertierung hier, die dies kompilieren lässt? Wenn ich operator char entferne oder es explicit mache, dann schlägt die Kompilierung an der gewünschten Stelle fehl. Die Klasse, aus der dieser Code extrahiert wird, benötigt sowohl die implizite Konvertierung als auch die operator[]. Gibt es eine Möglichkeit, das Verhalten zu verhindern, ohne die Konvertierung explizit zu machen?

+1

Haben Sie versucht, das Hinzufügen ein privater 'operator [] (char const *)'? –

Antwort

34

Der Grund für das Kompilieren von Zeilen ist, dass es bei der impliziten Konvertierung als 'a'["hello"]; interpretiert werden kann, was wiederum dem Schreiben von *(('a')+("hello")); entspricht, das ebenfalls kompiliert wird.

Auszug für den Standard:

5.2.1 Subskribierung:

... Die Ausdruck E1 [E2] ist identisch (per Definition) bis * ((E1) + (E2)) ...

die einfachste Abhilfe ohne die Umwandlung Betreiber explizit zu machen, ist der säumige Index-Operator zu erklären als gelöscht:

struct foo 
{ 
    operator char() const { return 'a'; } 
    int operator[](size_t i) const { return 1; } 

    // prevent accidental use of foo["hello"] 
    int operator[](char const*) const = delete; 
}; 
+3

... und durch Kommutativität, die äquivalent zu '* (E2 + E1)' und 'E2 [E1]'? Ich würde das nicht so selbstverständlich nennen ... –

+7

@UlrichEckhardt, ja, '" hallo "[0]' ist äquivalent zu '0 [" hallo "]'. – imreal

+4

Tatsächlich ist es nicht offensichtlich. Es ist C++. Es gibt Bücher voller C++ Fallen und Fallstricke. – Jerry101

0
f["hello"]; 

übersetzt in f.operator [] (index), wobei index der Wert des Zeigers ist, der auf "Hallo" zeigt. In Ihrem Fall ruft es den Operator [] (size_t i) auf. Also, ist absolut in Ordnung, dass Compiler nicht klagen. In der Tat würde der Indexwert al sein; arger Wert (Wert eines Zeigers), so besser vorsichtig sein, während [] Überlastung und prüfen, ob obere Grenze dort In der Tat, wenn Sie:

char *c = "hello"; // c is a pointer 
f[c]; // ok 
+0

Ummm, das ist völlig falsch und irreführend: Ein 'char *' ist nicht implizit in ein 'size_t 'konvertierbar, also wird' foo :: operator [] 'nie ausgewählt. Stattdessen' f 'wird in ein' char' umgewandelt, so dass es in '' a '["hallo"] 'übersetzt wird, was dasselbe wie' "hallo" [' a '] 'ist, was in ascii' 'hallo' [97]' ist Bitte sehen Sie sich die Antwort an, die Sie vor der Veröffentlichung akzeptiert haben. – marack