Анимация
JavaScript


Главная  Библионтека 

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

Компилятор

Результат

Сообщение об ошибке

MS VC++ 7.0 (2002)

Error

friend declaration incorrectly inteфreted as declaring a brand-new (and undefined) ordinary nontemplate function, even though we used template syntax

MS VC++- 7.1 (2003)

MS VC++ 8.0 (2005) beta

Итак, проблема для большинства компиляторов, которые не могут скомпилировать пример 8-1, заключается в том, что в нем специализация шаблона функции объявляется в другом пространстве имен.

Два неверных обходных пути

Когда этот вопрос только появился в Usenet, некоторые предлагали использовать объявление using (или, что то же самое, директиву using) и сделать объявление друга неквалифицированным.

namespace boost {

tempiate<typename Т> void checked delete( T* x ) { ... остальной код ... delete x;

using boost::checked delete;

или "using namespace boost;" class Test { -TestO { }

He специализация шаблона!

friend void checked delete( Test* x );

Это объявление друга относится к случаю 4: "4. В противном случае имя должно быть неквалифицированным и объявляет (возможно, повторно) обычную (нешаблонную) функцию." В действительности у нас получилось объявление новой нешаблонной функции : :checked delete(Test*) в объемлющем пространстве имен.

Если вы попытаетесь использовать этот код, многие из рассматривавшихся компиляторов отвергнут его, сообщая, что функция checked delete не определена, и все они сообщат об ошибке, если вы попытаетесь использовать отношение дружбы и поместить вызов закрытого члена в шаблон boost: :checked delete.

И наконец, один эксперт предложил немного изменить рассмотренный код - используя одновременно using и синтаксис шаблона о.

namespace boost {

template<typename Т> void checked delete( т* x ) { ... остальной код delete x;

using boost::checked delete; или "usi ng namespace boost;" class Test { -TestO { }

friend void checked„delete<>( Test* x ); Корректно?



Вероятно, этот код не совсем корректен: в стандарте нет указания на то, является ли корректным такое изменение, так что вопрос остается открытым и комитет по стандартизации языка еще не принял окончательного решения по этому вопросу. Скорее всего, этот код все же будет признан некорректным, а пока все KOMnHjiiiTopbi, с которыми я имел дело, отвергли его.

Почему этот код некорректен? Будем последовательны. Директива using существует для того, чтобы облегчить использование (use) имен - для вызова функций и применения имен типов в объявлениях переменных и параметров. Объявления должны подчиняться другим правилам. Аналогично тому, как вы должны объявлять специализацию шаблона в том же пространстве имен, что и сам шаблон (это нельзя делать в другом пространстве имен посредством using), вы должны и объявлять специализацию шаблона другом при помощи указания исходного пространства имен щаблона (без всяких using).

Резюме

Для объявления специализации шаблона функции в качестве друга вы можете использовать один из двух способов.

из примера 8-1

friend void boost::checked delete ( Test* x ); из примера 8-2: добавление о или <Test>

friend void boost::checked delete<>( Test* x ); или "<Test>"

В данной задаче продемонстрировано, что цена сокращения записи путем отбрасывания о или <Test> слишком высока - это существенная потеря переносимости.

> Рекомендация

Говорите то, что думаете. Указывайте, чего именно вы хотите добиться. Будьте точны. Если вы говорите о шаблоне и возникает вопрос, чего именно вы хотите добиться, - включите список (возможно, пустой) параметров шаблона.

Избегайте "темных углов" языка программирования, включая конструкции, которые несмотря на свою корректность склонны вводить в заблуждение программистов и даже компиляторы.

При объявлении специализации шаблона функции другом явно указывайте, как минимум, пустые угловые скобки о, например:

namespace boost {

tempiate<typename т> void checked deleteC т* x );

class Test {

fri end void boost::checked„delete (Test*x); плохо friend void boost::checked delete<>(Test*x); хорошо

Если ваш компилятор пока что не позволяет вам использовать ни один из этих способов для объявления отношения дружбы, сделайте необходимую функцию(и) открытой - добавив при этом комментарий, почему именно это сделано, и не забудьте вернуть все на место, когда новая версия вашего компилятора позволит вам справиться с рассмотренным синтаксисом.

" Имеются и другие обходные пути, но уж очень неприятные и длинные. Например, можно создать прокси-класс внутри пространства имен boost и сделать другом его.



Задача 9. Ограничения экспорта.

Часть 1: основы Сложность: 7

Разберемся с export - что о нем думают, что это такое на самом деле и почему все так старательно игнорируют эту возможность.

Вопрос для новичка

1. Что подразумевается под моделью включения для шаблонов? Вопрос для профессионала

2. Что подразумевается под моделью разделения для шаблонов?

3. В чем заключаются основные недостатки модели включения:

а) для обычных функций?

б) для шаблонов?

4. Как можно преодолеть недостатки из вопроса 3 при помоши стандартной модели разделения С+ + :

а) для обычных функций?

б) для шаблонов?

Решение

Стандартная возможность экспорта шаблонов зачастую оказывается неверно понятой, так что данная и следующая задачи призваны исправить ситуацию и внести ясность в этот вопрос.

На момент написания этого материала возможность экспорта поддерживалась только в одном коммерческом компиляторе. Компилятор Comeau", выпущенный в 2002 году и основанный на реализации С++ Edison Design Group (EDG)*, был первым (и пока единственным) компилятором с поддержкой экспорта. Поэтому не удивительно, что у программистов мало опыта по применению экспорта в реальных проектах; впрочем, ситуация должна кардинально измениться с появлением других компиляторов с поддержкой экспорта.

Вот о чем мы поговорим в этой и следующей задачах.

• Что такое экспорт и как следует его использовать.

• Задачи, для которых предназначается экспорт.

• Текущее состояние проблемы.

• Как экспорт влияет (зачастую неочевидно) на другие (на первый взгляд, никак не связанные с экспортом) части языка С+ + .

• Советы по эффективному использованию экспорта.

Рассказ о двух моделях

Стандарт С++ поддерживает две различные модели организации исходного текста шаблонов: старую, давно используемую модель включения и относительно новую модель разделения.

" www.comeaucomputing.com.

www.edg.com.



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