вторник, 26 июля 2011 г.

Зачем в checked_delete столько кода?

Если посмотреть на реализацию функции checked_delete в библиотеке Boost, то можно увидеть следующий код:
template<class T> inline void checked_delete(T * x)
{
    // intentionally complex - simplification causes regressions
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete x;
}

Для чего нужны такие сложности и почему упрощение приведет к регрессу? Дело вот в чем: чтобы корректно удалить объект, его тип должен быть полностью определен (complete type). Проверяется это в несколько этапов:
  1. Вызов оператора sizeof для неопределенного типа приведет к ошибке компиляции.
  2. На случай, если sizeof вернет 0 (в случает нестандартного расширения в компиляторе), создается массив с отрицательной длинной, что запрещено во всех компиляторах.
  3. Вторая строка нужна для компилятора Metrowerks CodeWarrior, который не будет инстанцировать первый typedef, пока он не используется.
  4. Преобразование результата sizeof к void нужно, чтобы избежать предупреждений во время компиляции.

Ссылки:
  1. Разъяснения от автора checked_delete.