2010-02-25 5 views
6

& zu bekommen, um eine Adresse einer Variablen zu erhalten, kann problematisch sein, wenn der Variablentyp operator&() überlastet ist. Zum Beispiel _com_ptr_ hat operator&() überladen mit einem Nebeneffekt der Modifizierung des Objekts.Die meisten portablen und zuverlässigen Weg, um die Adresse der Variablen in C++

Jetzt habe ich eine komplizierte Reihe von Vorlagen mit Funktionen wie folgt aus:

template<class T> 
void process(const T* object) 
{ 
    //whatever 
}  

template<class T> 
void tryProcess(T& object) 
{ 
    process(&object) 
} 

In tryProcess() I T einen T* Zeiger hält die Adresse des tatsächlichen Objekt vom Typ erhalten müssen.

Die obige Implementierung von tryProcess() funktioniert nur in Ordnung, wenn class Toperator&() nicht überlastet ist. Also wenn ich tryProcess<_com_ptr_<Interface>>() rufe kann ich unerwartete Ergebnisse bekommen - der überladene operator&() wird ausgelöst.

In another question die folgende Problemumgehung ist suggested:

template<class T> 
T* getAddress(T& object) 
{ 
    return reinterpret_cast<T*>(&reinterpret_cast<char&>(object)); 
} 

Mit einer solchen Funktion, die ich tryProcess() implementieren lassen sich wie folgt:

template<class T> 
void tryProcess(T& object) 
{ 
    process(getAddress(object)) 
} 

und wird immer das gleiche Verhalten unabhängig davon, ob class T hat operator&() überladen. Dies führt zu Null Overhead mit Optimierungen für Visual C++ 7 - der Compiler erhält, was zu tun ist, und ruft nur die Objektadresse ab.

Wie tragbar und Standard-Compilant ist diese Lösung für das Problem? Wie könnte es verbessert werden?

+0

Als Referenz für spätere Leser: C++ 11 standardisierte eine ordentlich umschlossene Version dieses Idioms als "std :: addressof": http://en.cppreference.com/w/cpp/ memory/addressof' –

Antwort

3

Es ist Standard-Beschwerde. Das Problem wurde dem Ausschuss ISO C++ in Bezug auf Probleme mit offsetof Implementierungen zur Kenntnis gebracht, die darauf eingingen. Unter den berücksichtigten Lösungen waren die Verschärfung der POD-Definition oder das Hinzufügen einer zusätzlichen Beschränkung für Typen, die mit offsetof zu verwenden sind. Diese Lösungen wurden zurückgewiesen, als die reinterpret_cast Lösung aufgezogen wurde. Da dies eine standardkonforme Lösung für das Problem darstellte, sah das Committee keine Notwendigkeit, zusätzliche Anforderungen an die offsetof anzufügen und behielt Korrekturen an den Implementierungen bei.

4

Boost addressof ist mit dem reinterpret_cast Trick implementiert, also würde ich sagen, es ist wahrscheinlich tragbar und standardkonform.

Here Sie können den betreffenden Code sehen.

+2

und glücklicherweise braucht man nicht mehr 'boost', da dies jetzt' std :: addressof' ist: http://en.cppreference.com/w/cpp/memory/addressof –

Verwandte Themen