2016-06-18 12 views
-2

Ich habe eine Menge von Funktionen mit solchen Unterschriften:Implizite Zeiger Conversions POD Zeiger

//libraries I can't change 
void f1(double *x); 
void f2(double *x1, double *x2); 
... 

Und eine Menge Code, die sie verwendet:

//my code 
double x; ... f1(&x); 
double x1[] = ...; double x2 = ...; f2(x1, &x2); 
... 

Aus irgendwelchen Gründen habe ich beschlossen, in verwenden Mein Code spezielle Klasse anstelle von gewöhnlichen verdoppelt:

Diese DoubleClass verhält sich wie doppelt mit einigen zusätzlichen Funktionalität, die ich will. Im Speicher ist DoubleClass das Gleiche wie Double. Es hat nur 1 Mitglied und Größe von (DoubleClass) == sizeof (double). Und so möchte ich mit so etwas wie

#define double DoubleClass 

alle Doppel in meinem Code neu deklarieren Aber ich Code nicht kompilieren kann, weil es keine Konvertierung von DoubleClass * ist * zu verdoppeln. Ich kann die Funktionen f1, f2 nicht ändern. Also wollte ich fragen, ob ich irgendwie eine implizite Umwandlung von DoubleClass * zu Double * definieren kann oder vielleicht gibt es ein paar Tricks, die das erlauben.

+6

Das ist wahrscheinlich eine sehr schlechte Idee, könnte Sie ein Backup mit etwas Überlegung, warum Sie eigentlich wollen, dies zu tun? –

+4

'# define' eines beliebigen Sprachen-Schlüsselwortes, einschließlich' double' ergibt ein undefiniertes Verhalten. Es gibt auch keine Möglichkeit, neue implizite Umwandlungen zwischen zwei unterschiedlichen Zeigertypen zu definieren (z. B. von "DoubleClass *" zu "double *"). Sie wären besser dran, wenn Sie mit Ihrem Editor eine globale Ersetzung von 'double' mit' DoubleClass' durchführen würden (außer natürlich in der Klasse 'DoubleClass'). Wenn Sie später entscheiden, Ihre 'struct DoubleClass' in' double' umzuwandeln, müssen Sie lediglich die Strukturdeklaration und '#define DoubleClass double' entfernen. – Peter

+0

Ich möchte dies tun, weil ich Vergleichsoperatoren etwas Funktionalität hinzufügen muss (ich möchte wissen, ob es Fälle gibt, in denen 2 sehr geschlossene Doppelgänger verglichen und als nicht gleich bestimmt werden, weil sie sich ein wenig unterscheiden). Vielleicht hat Peter Recht und Global Replacement mit Editor ist die beste Wahl. –

Antwort

0

könnten Sie mit Subtraktion von normalen Doppelwerten überprüfen, anstatt Operatoren zu überladen? wenn zwei subtrahiert verdoppelt 0 ist sie genau gleich sind *

machine precision floating point Beispiel Maschinengenauigkeit eine pingelig Sache ist *

+0

Sicher kann ich. Aber es gibt Hunderte von Stellen in dem Code, mit denen ich mich beschäftige, wo ich das überprüfen sollte. Und dieser Code wird von anderen kontinuierlich weiterentwickelt. Daher möchte ich in einigen Fällen eine einfache Möglichkeit zum Hinzufügen und Entfernen solcher Prüfungen zum Programm haben. –

1

Im Falle f1(), und der zweite Parameter von f2(), können Sie operator& außer Kraft setzen eine double* zurückzukehren :

struct DoubleClass { 
    double x_; 
    ... 
    double* operator&() { return &x_; } 
}; 

DoubleClass x = ...; 
f1(&x); 

DoubleClass x2 = ...; 
f2(..., &x2); 

Aber kein Betreiber in DoubleClass Überlastung können Sie mit dem ersten Parameter von f2() helfen, weil ein DoubleClass[] Array einfach nicht das gleiche wie ein double[] Array ist. Ein expliziter Typ-Cast wäre notwendig, um:

DoubleClass x1[] = ...; 
f2(reinterpret_cast<double*>(&x1[0]), ...); 

Oder einen Wrapper mit einem Umwandlungsoperator:

template <const int N> 
struct DoubleClassArray 
{ 
    DoubleClass arr_[N]; 
    ... 
    operator double*() { return arr_; } 
}; 

DoubleClassArray<...> x = ...; 
f2(x1, ...); 

Und so will ich alle Doubles neu deklarieren in meinem Code mit etwas wie

#define double DoubleClass 

Ich würde nicht vorschlagen, das zu tun. Aber wenn Sie das tun, müssen Sie sicherstellen, dass Sie die double innerhalb DoubleClass schützen, andernfalls wird es auch geändert.Definieren von Überlastungen wäre sicherer:

struct DoubleClass { 
    double x_; 
    ... 
    //DO NOT override operator&! 
}; 

void f1(DoubleClass *x) { f1(reinterpret_cast<double*>(x); } 
void f2(DoubleClass *x1, DoubleClass *x2) { f2(reinterpret_cast<double*>(x1), reinterpret_cast<double*>(x2); } 
... 

DoubleClass x; ... 
f1(&x); 

DoubleClass x1[] = ...; 
DoubleClass x2 = ...; 
f2(x1, &x2);