Utiliser &
pour obtenir l’adresse d’une variable peut être problématique si le type de variable a surchargé l’ operator&()
. Par exemple, _com_ptr_ a l’ operator&()
surchargé avec un effet secondaire de modification de l’object.
Maintenant, j’ai un ensemble compliqué de modèles avec des fonctions comme celle-ci:
template void process( const T* object ) { //whatever } template void tryProcess( T& object ) { process( &object ) }
Dans tryProcess()
je dois obtenir un pointeur T*
contenant l’adresse de l’object réel de type T
L’implémentation ci-dessus de tryProcess()
ne fonctionnera correctement que si la class T
n’a pas surchargé l’ operator&()
. Donc, si j’appelle tryProcess<_com_ptr_>()
je peux obtenir des résultats inattendus: l’ operator&()
surchargé operator&()
est déclenché.
Dans une autre question, la solution suivante est suggérée :
template T* getAddress( T& object ) { return reinterpret_cast( &reinterpret_cast( object ) ); }
Avec une telle fonction, je peux implémenter tryProcess()
comme suit:
template void tryProcess( T& object ) { process( getAddress( object ) ) }
et aura toujours le même comportement, que la class T
ait l’ operator&()
surchargé. Cela n’introduit aucune surcharge avec les optimisations sur Visual C ++ 7 – le compilateur obtient ce qu’il doit faire et obtient simplement l’adresse de l’object.
Comment portable et standard-compilant est cette solution au problème? Comment cela pourrait-il être amélioré?
C’est la plainte standard. La question a été scope à l’attention du comité ISO C ++ à propos des problèmes d’implémentation offsetof
implémentations. Parmi les solutions envisagées, citons le renforcement de la définition de POD ou l’ajout d’une ressortingction supplémentaire sur les types à utiliser avec offsetof
. Ces solutions ont été rejetées lorsque la solution reinterpret_cast
été mise en place. Etant donné que cela offrait une solution conforme au standard, le comité n’a pas offsetof
nécessaire d’append des exigences supplémentaires à l’ offsetof
et a laissé des correctifs pour les implémentations.
Boost addressof
est implémenté avec cette astuce addressof
donc je dirais que c’est probablement portable et conforme à la norme.
Ici vous pouvez voir le code en question.