Monday, August 07, 2006

 
std::swap и ADL
  В книге уважаемого мною автора Скота Мейерса "Эффективное использование С++" в правиле 25 даются рекомендация по использованию std::swap.
Это очень правильные рекомендации, им стоит придерживаться. Вот только жизнь часто вносит свои коррективы в теорию.
  Мейерс рассуждает о возможных действиях, когда необходимо как бы частично специализировать std::swap. "Как бы" из-за того, что частичная специализация функций в C++ и перегрузка функций в std:: запрещена стандартом.
  Что же делать, рассуждает он, если по-прежнему нужен способ, чтобы разрешить другим людям вызывать swap и иметь более эффективную шаблонную версию?

  В результате он принимает решение об объявлении функции swap в той же области видимости что и тип, являющийся ее аргументом. Вызов swap же не квалифицировать и поместить перед ним объявление using std::swap. Когда компилятор встречает вызов swap, он ищет, какую версию вызвать.

namespace foo
{
  template <class T> class bar {};
  template <class T> void swap(bar<T>&, bar<T>&) {}
}

void test()
{
  foo::bar<void> a, b;
  using std::swap;
  swap(a, b);
}

  Следуя правилам разрешения имен в С++ (используется ADL) будет найдена шаблонная функция foo::swap. При ее отсутствии будет вызвана шаблонная функция std::swap.
Стандарт 3.4.2 стих 2а.

  Итак, казалось бы жизнь прекрасна, проблема решена. Но не тут то было. Чудовищные нюансы поджидают нас в компиляторе gcc. Стоит лишь поместить функции test в ту же область видимости что и swap (в примере foo) и код сгенерированный gcc вызовет std::swap вместо foo::swap.
  Явная бага компилятора. Разработчики gcc же отвечают крайне невнятно. В последней версии gcc (на данный момент это 4.1.0) проблема по прежнему осталась.

Так что острожнее.
Beware of bugs.


Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?