Анимация
JavaScript
|
Главная Библионтека согласится со мной, что такое кардинальное изменение смысла объявления друга из-за опускания имени пространства имен, по меньшей мере, неожиданно. Таких конструкций следует избегать. Причина 3: удивляет компиляторы Случай 3 оказывается неожиданным и удивительным для компиляторов, он может оказаться неприменимым на практике, даже если мы проигнорируем приведенные ранее причины отказаться от данного способа. Испытаем коды, относящиеся к случаям I и 3, на разных компиляторах, и проанализируем результат. Воспринимают ли компиляторы стандарт так же, как и мы (дочитавшие книгу до этого места)? Будут ли, по крайней мере, самые мощные компиляторы вести себя так, как мы от них ожидаем? Оба ответа отрицательны... Сначала обратимся к случаю 3. пример 8-1 - еще раз namespace boost { tempiate<typename т> void checked delete( T* x ) { ... остальной код ... delete x; class Test { -TestO { } изначальный код friend void boost::checked deleteC Test* x ); i nt mainO { boost::checked delete( new Test ); Попробуйте скомпилировать этот код на вашем компиляторе, и мы сравним наши результаты (см. табл. 8.1). Таблица 8.1. Результат компиляции примера 8-1 разными компиляторами
Итак, наш тест показывает, что этот синтаксис плохо распознается современными компиляторами, один из них даже неоднократно меняет свое мнение по поводу данного кода в процессе разработки новых версий. Кстати, нас не должно удивлять, что компиляторы Comeau, EDO и Intel скомпилировали этот код, поскольку все они основаны на реализации EDO С++. Получается, что из пяти различных реализаций языка три (Digital Mars, gcc и Metrowerks) не понимают такой синтаксис, два других (Borland и EDO) понимают, и еще один никак не может определиться (Microsoft). Теперь изменим исходный текст так, чтобы он относился к случаю 1. пример 8-2: другой способ объявления друга namespace boost { tempiate<typename т> void checked de1ete( т* x ) { ... остальной код ... delete x; class Test { -TestO { } Альтернативный способ friend void boost::checked de1ete<> ( Test* x ); int main О { boost::checked delete( new Test ); Можно использовать и эквивалентную форму записи friend void boost::checked delete<Test>( rest* x ); Результат исследований более оптимистичен - такой код понятен уже для большего количества компиляторов (см. табл. 8-2.). Таблица 8.2. Результат компиляции примера 8-1 разными компиляторами
Случай 1 выглядит более привлекательно и безопасно - он работает почти на всех современных компиляторах, кроме gcc. Отступление: проблема в пространстве имен Заметим, что если бы интересующий нас шаблон функции не находился в другом пространстве имен, то мы бы могли спокойно использовать случай 1 практически на всех современных компиляторах. пример 8-3: checked delete не в пространстве имен Больше нет boost:: tempiate<typename т> void checked delete( T* x ) { 11 . . . прочий код ... delete x; "boost:" больше не нужен class Test { friend void checked delete<Test>( rest* x ); i nt mai n() { checked delete( new Test ); Результаты исследования приведены в табл. 8.3. Таблица 8.3. Результат компиляции примера 8-3 разными компиляторами
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [ 15 ] 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |