Используя &
получить адрес переменной может быть проблематичным, если тип переменной перегрузился operator&()
. Например, _com_ptr_ имеет operator&()
перегруженный с побочным эффектом изменения объекта.
Теперь у меня есть сложный набор шаблонов с функциями как это:
template
void process( const T* object )
{
//whatever
}
template
void tryProcess( T& object )
{
process( &object )
}
В tryProcess()
Я должен получить a T*
указатель, содержащий адрес фактического объекта типа T
.
Вышеупомянутая реализация tryProcess()
будет только работать хорошо если class T
не имеет operator&()
перегруженный. Таким образом, если я звоню tryProcess<_com_ptr_
Я могу получить неожиданные результаты - перегруженное operator&()
инициирован.
В другом вопросе предлагается следующее обходное решение:
template
T* getAddress( T& object )
{
return reinterpret_cast( &reinterpret_cast( object ) );
}
С такой функцией я могу реализовать tryProcess()
следующим образом:
template
void tryProcess( T& object )
{
process( getAddress( object ) )
}
и будет всегда получать то же поведение, независимое от ли class T
имеет operator&()
перегруженный. Это начинает нуль наверху с оптимизации на на Visual C++ 7 - компилятор добирается, что сделать и просто получает объектный адрес.
Насколько портативный и стандартный-compilant это решение к проблеме? Как это могло быть улучшено?
Это стандарт-жалоба. Проблема была доведена до сведения комитета ISO C ++ в связи с проблемами с смещением
реализаций, которые сломались на этом. Среди рассмотренных решений было ужесточение определения POD или добавление дополнительных ограничений на типы, которые будут использоваться с смещением
. Эти решения были отклонены, когда было предложено решение reinterpret_cast
. Поскольку это предлагало способ решения проблемы, соответствующий стандарту, комитет не усмотрел необходимости добавлять дополнительные требования к смещению offsetof
и оставил исправления в реализациях.
Boost addressof
реализован с помощью трюка reinterpret_cast
, так что я бы сказал, что это, вероятно, переносимо и соответствует стандартам.
Здесь вы можете увидеть код, о котором идет речь.