2016-06-12 8 views
1

Nehmen wir an, ich entwickle eine Klasse Vec<T>, die einen mathematischen Vektor mit Elementen des Typs T darstellt.Überladungstyp Umwandlung in Initialisierungsliste

Der Einfachheit halber ich den Konstruktor erstellt, der nimmt std::initializer_list:

Vec(std::initializer_list<T> l) 
    : size(l.size()) 
{ 
    data = new T[size]; 
    std::copy(l.begin(), l.end(), data); 
} 

So, jetzt kann ich die folgenden Dinge tun:

v += Vec<int>({ 1, -1 }); 
bool equal = (v == Vec<int>({ 8, 9 })); 

Und so weiter ... Aber es wäre toll, wenn Ich könnte es noch kürzer und sauberer schreiben:

v += { 1, -1 }; 
bool equal = v == { 8, 9 }; 

Wie erreiche ich so ein Verhalten? Ich nehme an, ich könnte einen Typumwandlungsoperator auf std::initializer_list überladen, aber ist das überhaupt üblich? Wie schlimm ist es für die Kompilierungszeit und -leistung und funktioniert es überhaupt?

Was ist mit std::vector, unterstützt es so etwas in C++ 11?

EDIT:

So, hier ist meine operator+=:

Vec<T> & operator+=(const Vec<T> &v) 
{ 
    assert(size == v.size); 
    for (int i = 0; i < size; ++i) 
     data[i] += v.data[i]; 
    return *this; 
} 

Die Antworten in den Kommentaren korrekt sind, initializer_list tatsächlich funktioniert nach Zuweisungsoperator:

v += {2, 3}; 
v -= {2, 3}; 

Ich habe versucht, etwas zu schreiben:

v = v + {2, 3}; 

Deshalb hat es nicht funktioniert.

Also ist die Schlussfolgerung: Sie können es so nach Zuweisung und Compound-Zuweisung-Operatoren verwenden, aber für binäre arithmetische Operatoren und Vergleiche wird es nicht funktionieren, bin ich richtig? Ich denke, das Erstellen von benutzerdefinierten Literalen ist auch keine Option.

By the way, wie etwa:

const Vec<float> a{ 1.01, 2.02 }; // error: conversion from 'double' to 'float' requires a narrowing conversion test_app 
const Vec<float> b{ 1.01f, 2.02f }; // works, obviously 

Kann ich etwas tun, implizite Konvertierung im ersten Fall zu aktivieren?

EDIT2

Hier ist die operator+:

friend Vec<T> operator+(Vec<T> v, const Vec<T> &w) 
{ 
    v += w; // reuse compound assignment 
    return v; // return the result by value (uses move constructor) 
} 
+1

Zeigen Sie Ihren 'Operator + ='. Dies sollte bereits so funktionieren, wie Sie es beschreiben. –

+1

'v == {8, 9}' ist syntaktisch ungültig. – cpplearner

+0

['operator + =' funktioniert einfach] (http://rextester.com/NBE83364) ohne zusätzlichen Aufwand. Ich würde mir auch vorstellen, dass die meisten anderen Betreiber dies tun würden. 'operator ==' ist eine Ausnahme; von oben bin ich nicht ganz sicher, warum es hier besonders ist. –

Antwort

1

Leider v + {1, 2} für grammatikalische Regeln nicht ein wohlgeformter Ausdruck in C++ ist. Die meisten binären Operatoren nehmen nur Ausdrücke für jeden der Operanden, und die Klammerliste ist kein Ausdruck. Der zusammengesetzte Zuweisungsoperator += ist speziell, weil die Zuweisung auch eine Initialisierungsklausel für den rechten Operanden akzeptiert, so dass v += {1, 2} funktioniert.

Einige Alternativen:

operator+(v, {1, 2}) 
v + Vec<int>({1, 2}) 
+0

Danke für die Antwort. Eine andere Option, die ich denke, ist, Funktionen wie 'add' oder' isEqualTo' zu erstellen, wo man leicht Initialisierungslisten wie folgt übergeben kann: 'v.isEqualTo ({1,2,3});' –

1

Wie wäre es v.equals({8, 9})? Auch wenn v + {1, 2, 3, 4} nicht möglich ist, könnten Sie immer noch den Komma-Operator überladen, wie viele Vektor-Matrix-Implementierungen tun (nicht für int, sondern für einen bestimmten Typ wie: v + (V(1), 2, 3, 4), fügen Sie Makros hinzu, wenn Sie sie mögen).

+0

Ja, habe ich gewählt, um mit Methoden wie Ihrem "Gleichen" zu gehen, sehen Sie meinen Kommentar zur angenommenen Antwort. BTW, Ich habe Komma-Implementierungen in ein paar Bibliotheken (wie OpenCV zum Beispiel) gesehen, aber ich würde lieber von diesem Design fern bleiben. Keine besonders offensichtliche Schnittstelle) –

Verwandte Themen