Анимация
JavaScript
|
Главная Библионтека приемлемую альтернативу (не говоря уж о недостатке времени - планировалось выпустить окончательный вариант стандарта в следующем, т.е. 1997 году). Из-за всего этого производители компиляторов единогласно не хотели спешить с включением модели разделения в первый стандарт [С++98]. Вместо этого предлагалось "обкатать" идею как следует и подготовить с с к включению в следующий стандарт С++. Они не отказывались от идеи раздельной компиляции в принципе, но чувствовали, что в том виде, в котором ее предложено внести в стандарт, она еще сыровата. Тем не менее, они проиграли, и ключевое слово export применительно к шаблонам оказалось в стандарте. Как я говорил ранее, большинство (незначительное) в комитете считало, что невозможно выпускать стандарт, в котором нет "раздельной" компиляции шаблонов, в то время как для обычных функций в С такая раздельная компиляция давно имеется и широко применяется. Несколько производителей компиляторов уже поэкспериментировали с различными видами "раздельной" компиляции шаблонов, и эта идея казалась, в принципе, обоснованной. Словом, export остался в стандарте из принципиальных соображений, и из этих же соображений не следует чернить его сверх меры. Подчеркнем, что ведущие производители компиляторов были не против принципа раздельной компиляции шаблонов вообще, а против конкретной формулировки в стандарте языка. Они полагали, что следовало дать дополнительное время на анализ этого вопроса и принятие верного решения. Хотя некоторые из экспертов, которые в 1996 году голосовали за включение export в стандарт языка, сейчас считают это решение ошибочным, поставленные тогда цели были вполне правильными. Остается надеяться, что со временем они будут достигнуты. А пока что нам остается набираться опыта с помощью первого компилятора, который реализовал эту возможность (Comeau 4.3.01, 2002 год). Опыт работы с экспортом Единственный в мире производитель компилятора с поддержкой export для шаблонов - EDO - сообщил о том, что это наиболее сложная в реализации возможность С+ + , которая требует объема работы не меньшего, чем любые три другие возможности языка (например, пространства имен или шаблоны-члены классов). Потребовалось более трех человеко-лет работы только для кодирования и тестирования, не считая проектирования. Для сравнения - реализация языка Java теми же тремя программистами потребовала только два человеко-года. Почему же поддержка export так сложна и трудно реализуема? Две основные причины можно сформулировать следующим образом. 1. Экспорт базируется на поиске Кенига. Большинство компиляторов все еще не в состоянии реализовать корректный поиск Кенига даже в пределах одной единицы трансляции (попросту говоря, в одном исходном файле). Экспорт же требует выполнения поиска Кенига в нескольких единицах трансляции. (Дополнительную информацию о поиске Кенига можно найти в [SutterOO].) 2. Концептуально экспорт требует от компилятора одновременной работы с несколькими таблицами символов. Инстанцирование экспортированного шаблона может вызвать каскадные инстанцирования в других единицах трансляции, и каждое инстанцирование должно иметь возможность обратиться к объектам, которые существуют (или "как бы существуют") при синтаксическом анализе определения шаблона. В С++ уже достаточно сложна работа только с одной таблицей символов. Обсуждение этого вопроса было бурным, и мнения членов комитета разделились. Так, в марте 1996 года голоса разделились как 2 к 1 против раздельной компиляции шаблонов; однако уже в июле того же года, когда ключевое слово export было внесено в стандарт, перевес голосов в пользу такого решения составил 2 к 1. а в случае экспорта шаблонов приходится иметь дело с произвольным количеством таких таблиц. До чего доводит экспорт 2. Поясните, каким образом экспорт изменяет смысл других конструкций С++? Ключевое слово export порой неожиданным образом влияет на другие возможности языка. Многие из них никак не упомянуты в стандарте. В частности, export экспортирует не только шаблон, с которым употребляется. • Если некоторые функции и объекты в безымянных пространствах имен используются в экспортируемых шаблонах, то теперь они должны быть доступны не только в пределах своих единиц трансляции. Аналогично, некоторые статические функции и объекты, используемые в экспортируемых шаблонах, которые ранее были видимы только в пределах своего файла, теперь должны иметь внешнее связывание (или, по крайней мере, вести себя так, как будто они им обладают). Это противоречит предназначению безымянных пространств имен и описания функций и объектов как статических, что должно делать их имена строго внутренними для соответствующих единиц трансляции. (Хотя статические функции и объекты объявлены устаревшей и нежелательной конструкцией языка, и вы должны вместо описания static использовать безымянные пространства имен, они остаются частью стандарта С++.) • Разрешение перегрузки также должно быть способно выполнять разрешение с использованием имен из различных единиц трансляции - включая перегруженные имена из произвольного количества безымянных пространств имен. Главное преимущество размещения внутренних функций в безымянных пространствах имен (или объявление их статическими) состоит в их "скрытии", так что вы можете давать им простые имена, не беспокоясь о конфликтах имен или перегрузке при использовании нескольких исходных файлов. Теперь же эти функции могут участвовать в разрешении перегрузки при их использовании в экспортируемых шаблонах. Таким образом, для скрытия имен функций и объектов, используемых в экспортируемых шаблонах, недостаточно их размещения в безымянных пространствах имен, что, конечно же, противоречит изначальной идее безымянных пространств имен и статических объявлений. • Возникают также новые разночтения и потенциальные нарушения правила одного определения. Например, класс может иметь несколько друзей в различных единицах трансляции, и в инстанцировании могут участвовать объявления этого класса из разных единиц трансляции. Если это так, то какой именно набор правил доступа следует применять? Это может показаться очень мелким вопросом, а многие подобные ошибки - безвредными, но последствия нарушения правила одного определения становятся все более существенными у ряда распространенных компиляторов (см. один из примеров в [Sutter02c]). Трудность корректного использования 3. Чем именно export мешает программисту? Корректно использовать экспортируемые шаблоны несколько сложнее, чем обычные. Вот три примера, иллюстрирующие это утверждение. Пример I. Становится проще, чем раньше, написать программу с трудно предсказуемым смыслом. Так же, как и в модели включения шаблонов, зачастую экспортируемый шаблон имеет различные пути инстанцирования и каждый из них имеет свой собственный контекст. На возражение наподобие того, что та же проблема наблюдается и в случае функций, определенных в заголовочном файле, т.е. встраиваемых (inline). можно возразить, что проблема с шаблонами существенно большая, поскольку появляется больше возможностей для изменения смысла имен, в частности, потому что шаблоны работают с более мощными множествами имен, чем закрытые функции. Шаблоны используют зависимые имена, т.е. имена, которые зависят от аргументов шаблонов. Поэтому при каждом инстанцировании шаблона с одинаковыми аргументами пользователь шаблона должен обеспечить одинаковый контекст (например, множество перегруженных функций, работающих с типами аргументов шаблона). Это требуется для того, чтобы предотвратить непредумышленное инстанцирование, имеющее разный смысл в разных файлах, что противоречит правилу одного определения. Почему ожидается, что это будет большей проблемой в модели экспорта, чем в модели включения? Пото.му что главное, чем отличаются эти модели, - это выполнение поиска имен в разных единицах трансляции при экспортировании, чего не требуется для реализации других возможностей стандартного С++. Пример 2. Компилятору сложнее генерировать высококачественную диагностику, помогающую программисту. Сообщения об ошибках, связанные с шаблонами, и без того пользуются дурной славой слишком громоздких и трудно понимаемых из-за длинных имен. Каскадные инстанцирования при экспортировании шаблонов вряд ли добавят ясности в эти сообщения. Кроме того, экспортирование добавляет как бы новое измерение в пространстве сообщений об ошибках. Сообщения типа "ошибка в строке X, вызванная инстанцированием функции Y, вызванным инстанцированием Z, вызванным инстанцированием..." теперь должны указывать еще и единицы трансляции, в которых это произошло. В результате каждая строка такой "поэмы об ошибках" будет содержать разные единицы трансляции. Выявление нарушений правила одного определения - уже достаточно сложная проблема, но в такой ситуации она становится во много раз сложнее. Столкнувшись с такими проблемами, многие программисты сочтут сообщения об ошибках в обычных шаблонах легко читаемыми и понятными. Пример 3. Экспорт накладывает новые ограничения на среду разработки. Среда разработки - это не только .срр и .h-файлы, и многие современные инструменты разработки не в состоянии работать с выглядящими циклическими зависимостями при изменении объектных файлов в процессе компоновки (в предыдущей задаче отмечалось, что экспорт только скрывает зависимости, так что при изменении файла с экспортируемым шаблоном надо перекомпилировать не только его, но и все его инстанцирования). Как заметил один из специалистов мирового класса по шаблонам, Джон Спай-сер (John Spicer) из EDG, "экспорт сложен по самой своей природе и требует огромной работы для того, чтобы осознать все его последствия. Трудно дать простые советы по его использованию, которые уберегут программистов от неприятностей" [выделено мной]. Потенциальные преимущества экспорта 4. В чем заключаются реальные и потенциальные преимущества export? Теперь, когда программистам доступна реализация экспорта, самое время разо-браться, как же следует использовать новые возможности. Вот основные преимущества, которые можно надеяться получить от использования экспорта шаблонов. /. Ускорение построения приложений. Все еще остается открытым вопрос о влиянии экспорта шаблонов на скорость построения реальных приложений, использующих шаблоны. При широком внедрении и использовании экспорта шаблонов можно надеяться, что исследования в этой области позволят выработать как новые технологии, так и рекомендации по созданию кода, для которого будет явным увеличение скорости построения приложения. В частности, есть надежда, что единицы трансляции будут менее чувствительны к изменениям в определении шаблона, а значит, их обработка при необходимости перекомпиляции будет выполняться быстрее. 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 |