Трюки от Крыса Крис Касперски Хакер, номер #103, стр. 103-120-3 А вот язык Си++, претендующий на обратную совместимость с Си, при работе с диграфами наталкивается на серьезные проблемы, приобретая неоднозначность интерпретации: одна и та же конструкция может быть прочитана двояко в зависимости от того, выполнять ли в ней подстановку диграфов или нет. Рассмотрим ситуацию на следующем примере. Допустим, в глобальном пространстве имен (global namespace) мы имеем класс, именуемый (для определенности) X. Допустим также, что мы хотим передавать класс X какому-нибудь другому классу в качестве аргумента (например, классу std::vector), причем передавать не абы как, а непременно в виде шаблона (template), ведь шаблоны - это, во-первых, очень модно, а во-вторых, жутко (не)удобно! Но как бы там ни было (о вкусах не спорят), задача поставлена, и ее надо решать. Очевидное решение — написать «std::vector<::X>», и на некоторых компиляторах это будет работать. Как ты уже, наверное, понял, этими компиляторами окажутся Microsoft Visual C++, Borland C++, ранние версии GCC, то есть все те, кто не поддерживает диграфов и потому трактует конструкцию «std::vector<::X>» однозначно. Проблемы возникают при попытке скормить эту штуку свежим версиям GCC (или любому другому компилятору с поддержкой диграфов). Комбинация «<:» заменяется «[», в результате чего вся конструкция превращается в «std::vector[:X>», выдавая ошибку транслятора и вызывая естественное недоумение программиста: «Что здесь не так?! Ведь еще вчера компилировалось!» Одно из возможных решений состоит в разделении «<» и «::X>» символом пробела. Конструкция принимает вид «std::vector< ::X>», и конфликтов с диграфами больше не возникает. Анализ исходных текстов, выловленных на бескрайних просторах Сети, показывает, что очень многие программы Си++ страдают подобными конфликтами и отказываются компилироваться свежими версиями GCC. Забавно, но некоторые разработчики прямо указывают требуемую версию транслятора в FAQ, предостерегая от использования более новых («багистных») версий. В действительности это не баг. Это фича! И теперь ты знаешь, как с ней обращаться. |