2013-06-20 3 views
8

Ist es möglich, eine Klasse, so dass diese gültig zu schreiben:Kann ich eine implizite Initialisierung auf 0 überladen?

Foo a; 
Foo b = 0; 
Foo c = b; 
Foo d(0); 
Foo e(1); 
Foo f = Foo(1); 

Aber diese sind nicht:

int x; 
Foo a = x; 
Foo b = 1; 
Foo c = 2; 
//etc 

Im Wesentlichen meine Regel ist „Eine Konstante 0 ist implizit umwandelbar in ein Foo , aber kein anderer Wert ist "

+0

Was ist mit 'Foo e (1);'? Wie ist das gültig? –

+0

@LuchianGrigore: Sind sie semantisch identisch? Wenn ja, kann ich das für ungültig erklären. – Eric

+1

Vielleicht können Sie versuchen, mit einem Konstruktor eine 'std :: nullptr_t' (nur eine Idee ...) –

Antwort

5

Wenn es Ihnen nichts ausmacht Foo b = nullptr; funktioniert, ist es ziemlich einfach zu hacken. Habe einen expliziten Konstruktor von int und einen impliziten von std::nullptr_t.

Wenn Sie daran arbeiten, bin ich mir nicht sicher, ob es möglich ist. Die einzige Möglichkeit, zwischen einem Literal 0 und anderen Integer-Literalen zu unterscheiden, ist die implizite Umwandlung in Zeiger und nullptr_t. So nullptr wird einen nullptr_t Parameter zu einem Zeiger-Parameter bevorzugen, so dass Sie beide Konstruktoren nullptr Argumente ausfiltern können. Jedoch sind die Umwandlungen von 0 zu Zeigern und nullptr_t von gleichem Rang, so dass dies 0 Argumente mit einer Mehrdeutigkeit töten würde.

Hmm ... so etwas wie dies funktionieren kann:

class Foo { 
    struct dummy; 
public: 
    explicit Foo(int); // the version that allows Foo x(1); 
    Foo(dummy*); // the version that allows Foo x = 0; 
    template <typename T, 
      typename = typename std::enable_if< 
       std::is_same<T, std::nullptr_t>::value>::type> 
    Foo(T) = delete; // the version that prevents Foo x = nullptr; 
}; 

Ich habe nicht wirklich versucht. Theoretisch sollte die Vorlage nur dann an der Überladungsauflösung teilnehmen, wenn das Argument nullptr lautet, da SFINAE andernfalls das Argument löscht. In diesem Fall sollte es jedoch besser als der Zeigerkonstruktor sein.

0
Foo e(1); 

Wird ca lle ein nicht expliziter Konstruktor von Foo, der ein int als Argument nimmt. Im Wesentlichen wird diese Zeile dasselbe tun, indem versucht wird, int mit diesem int Konstruktor in Foo zu konvertieren.

Foo b = 1; 

Sie können nicht verhindern, dass bestimmte Werte dieses int direkt verarbeitet werden. Wenn Sie Ihren Konstruktor explicit haben, können Sie die nächste Zeile auch nicht schreiben.

Foo b = 0; 

gx_ hat korrekt angegeben, dass 0 in std :: nullptr_t konvertiert werden kann. Folgendes wird in Bezug auf Ihre Absicht funktionieren.

Foo(std::nullptr_t x) : member(0) { } 
explicit Foo(int c) : member(c) { } 
// ... 
Foo a = 0; // compiles 
Foo b = 1; // doesn't compile 

// Note: 
int do_stuff (void) { return 0; } 
Foo c = do_stuff(); // doesn't compile 
+0

Nein, Direkt- vs. Kopierinitialisierung. –

+1

Wie wäre es mit einem expliziten Foo (int); plus einem 'Foo (nullptr_t);'? –

+0

+1, eher seitlich gedacht aber möglich – Pixelchemist

-1

Eine Idee, die ich hatte, war:

Foo(const uint32_t c) : member(0) { static_assert(c == 0, "Nope"); } 
explicit Foo(uint32_t c) : member(c) { } 

dies vernünftig Verhält sich?

+2

Das wird nicht mal kompilieren. Was die Überladungsauflösung betrifft, sind ein 'const uint32_t'-Parameter und ein' uint32_t'-Parameter die gleichen. –

-1

ich zugeben, dass ich nicht vollkommene Beherrschung der rvalue Semantik von C++ 11 noch nicht erreicht haben, aber dies scheint zu tun, was Sie wollen:

class Foo 
{ 
    public: 
    Foo(int&&) {} 
}; 

int main() 
{ 
    Foo a(123); 
    int x = 123; 
    Foo b(x); // error here, line 11 
    return 0; 
} 

Ergebnis:

prog.cpp:11: error: cannot bind ‘int’ lvalue to ‘int&&’

Kommentare willkommen, wenn dieser Code irgendwelche Vorbehalte hat, die ich nicht bemerkt habe, oder wenn Sie mich beruhigen können, dass es nicht tut.

+0

Interessant, aber ich ziele auf den speziellen Fall von 'x == 0'; – Eric

+0

@eric Ah, habe das nicht bemerkt. Du hast gesagt "Foo e (1);" sollte gültig sein: / – Oktalist

Verwandte Themen