2010-02-25 14 views
6

El uso de & para obtener una dirección de una variable puede ser problemático si el tipo de variable se ha sobrecargado operator&(). Por ejemplo, _com_ptr_ tiene operator&() sobrecargado con un efecto secundario de modificación del objeto.La forma más portable y confiable de obtener la dirección de la variable en C++

ahora tengo un complicado conjunto de plantillas con las funciones de la siguiente manera:

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

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

En tryProcess() necesito para obtener un puntero T* la celebración de la dirección del objeto real del tipo T.

La implementación anterior de tryProcess() solo funcionará bien si class T no tiene operator&() sobrecargado. Entonces, si llamo al tryProcess<_com_ptr_<Interface>>(), puedo obtener resultados inesperados: se activa el operator&() sobrecargado.

En another question la siguiente solución es suggested:

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

Con una función tal que pueda poner en práctica tryProcess() de la siguiente manera:

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

y siempre obtener el mismo comportamiento independiente de si class T tiene operator&() sobrecargado. Esto introduce una sobrecarga cero con optimizaciones en Visual C++ 7: el compilador obtiene qué hacer y solo obtiene la dirección del objeto.

¿Cuán portátil y estándar compilant es esta solución al problema? ¿Cómo puede ser mejorado?

+0

Para referencia de lectores posteriores: C++ 11 estandarizó una versión pulcramente envuelta (anteriormente 'boost') de este modismo, como' std :: addressof': http://en.cppreference.com/w/cpp/ memory/addressof' –

Respuesta

3

Es una queja estándar. El problema fue llevado a la atención del comité ISO C++ en relación con los problemas con las implementaciones offsetof que rompieron con esto. Entre las soluciones consideradas estaban ajustar la definición de POD, o agregar una restricción adicional en los tipos que se utilizarán con offsetof. Esas soluciones fueron rechazadas cuando se presentó la solución reinterpret_cast. Como esto ofrecía una forma de cumplir con el estándar, el comité no vio la necesidad de agregar requisitos adicionales al offsetof, y dejó correcciones a las implementaciones.

4

Boost addressof se implementa con ese truco reinterpret_cast así que diría que es probablemente portátil y de conformidad con el estándar.

Here puede ver el código en cuestión.

+2

y afortunadamente, uno ya no necesita 'boost', ya que ahora es' std :: addressof': http://en.cppreference.com/w/cpp/memory/addressof –

Cuestiones relacionadas