Доброе время суток! Тут недавно попытался использовать больше одного анонимного класса на MSVC++ 2005 Express Edition, и тут же мне linker выдает такой фокус: вот пример: Код (Text): template<int n> class A { public: A() { printf("A.ctor(%i); \r\n", n); } }; class : public A<1> {}A1; class : public A<2> {}A2; Такой же код, только под MSVC++ 2008 Express Edition SP-1 RUS работает нормально.
"Нормальная" работа этого кода - это такой же "фокус", как и возникновение сообщения об ошибке. Приведенный код не является валидным с точки зрения С++ (см. стандарт, 7.3).
nop_ Какой-то у тебя не такой стандарт как у меня Мы ведь о ISO/IEC 14882:1998 говорим? 7.3 это вроде namespace-ы... Да и нет здесь никакого криминала, все кошерно... Подтверждаю, MSVC 2008 нормально работает. gcc 4.3 тоже, но c warning'ом: "non-local variable <anonymous class> A2 uses anonymous type". Если добавить "static", warning пропадает.
Действующий стандарт - ISO/IEC 14882:2003 Хотел написать "7/3", но это тоже не то, там все несколько сложнее и завязано на linkage. В некоторых контекстах такой синтаксис допустим, в некоторых - нет. Это говорит только о том, что "MSVC 2008 нормально работает. gcc 4.3 тоже". и больше ни о чем. msvc, например умеет биндить временные объекты к неконстантной ссылке. Только из этого не следует что в С++ есть такая возможность.
nop_ Де-юре, разве что. Лучше рассчитывать на старый добрый 98-й. Ниче не понял что есть 7/3 ??? Дык, стандартом-то не сильно скомпилируешь поэтому все сводится к тому, работает или нет на конкретном компиляторе. long long тоже стандартом вроде не одобрен, тем не менее, покажите мне компилятор, в котором оный не поддерживается Я хочу сказать, что эта конструкция в принципе не противоречит стандарту. Но там где шаблоны - всегда неприятности, здесь и стандарт и компилеры просто не успевают за фантазией програмеров
"Старый добрый" уже не имеет статуса стандарта, хотя отличий там совсем немного, т.к. он содержит в основном исправления. Ниче не понял что есть 7/3 ??? Это между 7 и 7.1 =) Но я был не прав насчет этого пункта. Различные расширения компиляторов это одно дело, а вот несоответствия стандарту - совершенно другое. Если имя определяемого объекта('A1', 'A1') находится в таком контексте где оно имеет external linkage, то противоречит, т.к. в этом случае тип также должен иметь external linkage, но анонимный класс не имеет никакого связывания по определению. Использование 'static' в namespace scope приводит к тому что имя получает internal linkage. Предупреждение "non-local variable <anonymous class> A2 uses anonymous type" тоже по делу: объекты определенные в пределах функций не имеют никакого связывания. Т.е: Код (Text): class : A<1> {} A1; // error static class : A<2> {} A2; // ok void f() { class : A<3> {} A3; // ok } Шаблоны здесь в общем-то ни при чем.
nop_ А, это вот это: In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class... понял, наконец... Да где же здесь несоответствие? По логике - да, но в стандарте я помню только требование статичности к глобальным union'ам. Кроме того, в твоей фразе тоже того... логика хромает ибо в цепепе понятие связывание для типа вобщем-то смысла не имеет, поскольку по структуре языка типизация есть compile- а не run- time. Возможно. Но такие мутные конструкции я бы вообще пользовал бы аккуратно. Шаблоны для цепепе-компилеров - всегда trying by fire, поэтому если возникло сомнение, я бы попробовал ту же конструкцию, но без шаблонов. [offtop] вот помню, лет семь назад, сочинял библиОтеку под работу с фиксированой точкой для Borland 3.1 чо-то типа: Код (Text): template <int a, int b> inline Fix<a+b> operator *(const Fix<a>& x, const Fix<b>& y) { return Fix<a+b>(x.val * y.val); } От такого невинного по нынешним временам кода этот с позволения сказать компилер скрючило и он издох в мучениях. И я окончательно перебрался на Watcom. [/offtop]
В global scope это не должно компилироваться. Что есть 'статичность'? Связывание имеет смысл для имен, имена вводятся объевлением/определением - для этого требуется имя типа объявляемого объекта. Вероятно я некорректно выразился, но именно я имел ввиду. Как это кореллирует с наличием/отсутствием связывания? Если объект(такой как 'A1' например) определен в namespace scope (сюда в том числе входит и global scope) то (без дополнительных условий) это значит что он может быть доступным из других едениц компиляции(TU). Для этого требуется 'extern' объявление. А для этого требуется имя типа, которого у нас нет. + на момент компиляции TU с определением 'A1' компилятор ничего не знает о том, будет ли где-нибудь в других TU необходимость в 'extern' объявлении, да и в принципе не может знать, т.к. линковка с другими TU может осуществляться намного позднее. Поэтому ему _необходимо_ имя типа определенного объекта. Определение такого объекта в block scope (теле функции), как и определение его с квалификатором 'static' снимает необходимость наличия имени в связи с тем, что в других TU он не будет (и в принципе не может быть) востребован. Это действительно так.
nop_ Кто сказал? static'ность то есть внутреннее связывание. Я, в принципе, понял, что имеется ввиду Да понял я , понял. Я даже готов согласится. Мутное это дело - раздельная компиляция и все что с ней связано. У нас нет, а у компилятора есть. Не пугают же никого глобальные переменные в неименованных namespace'ах. Не вижу принципиальной разницы. По стандарту, еще раз повторю, исключительным случаем является только глобальное неименованное union (ну, это понятно почему).
Defect Report#389. Unnamed types in entities with linkage На всякий случай: DR#216. Linkage of nameless class-scope enumeration types DR#319. Use of names without linkage in declaring entities with linkage + Если тебе нравится проверять валидность кода с помощью компилятора - http://www.comeaucomputing.com/tryitout для внутреннго связывания используется отдельный термин - 'internal linkage'. А толку? оно должно совпадать с именем в другом TU. только вот без наличия 'нормального' имени это невозможно обеспечить. Оно обязано ходить вместе со 'static'(9.5/3). Это является требованием. О каком "исключении" ты говоришь?
nop_ Это один их многих. Более того, я не знаю ни одного проекта на нем созданного. Я протестую, ваша честь! Это мелочные придирки Еще раз: чем это отличается от имен в неименованных namespace'ах? linkage у них external? Он самый. По крайней мере в известных мне компилерах. Их других единиц компиляции к ним доступ есть? Фиг. Хотя "грязным хаком" сделать можно. И кого это смущает? Это я напутал, если честно, это требование немного в другом случае работает. Да и смысл union'а совсем другой. Но в общем и целом я согласен, фиговая конструкция, ИМХО. Будем считать, меня ты убедил. Осталось убедить разработчиков компиляторов А до тех пор придется учится самим не простреливать себе ногу. Черт, неужели кому-то без этого скучно?
вот этого не надо делать Хоть на 2008 работает и то хорошо Нет, суть была в чем - я создаю некую библиотеку (в данном случае, стандарт Си++ меня не интересует, так как библиотека полностью под windows, и переносимость хотелось в рамках msvc++ компиляторов), там есть классы с виртуальными функциями, т. е. достаточно унаследоваться от этого класса и перегрузить функцию и вуаля. Но вот создавать новый тип, как-то не очень, более наглядно и красивее (ИМХО) выглядит именно анонимные классы. Вот и все. А веревку достаточной длины что бы прострелить себе ногу, кхм, потянул тогда когда решил программировать на C/C++
а) исходный код этот компилятор не компилирует. б) на прктике - это единственный компилятор, который постулирует (и не просто так!) 100% standard conformance. Я не знаю наколько это актуально (особенно на _этом_ форуме) для большинства, но для меня соответствие (кода) стандарту - хм... это прсто _должно_ быть... я не знаю как сказать по другому. workaround's, да, они бывают... Это не значит что их не существует, ведь правда? =) Да и впорос на самом деле стоит по другому - какой процент проектов способен откомпилировать тот же comeau. Для legacy (*) - 99% ноль (без шаманства с флагами, etc.), по крайней мере, противоположных примеров (кроме того 1-го процента) я не знаю... Хорошо это или плохо - по этому поводу я спорить не готов. Какое интересное утверждение. хотелось бы увидеть ссылку на стнадрт. Особенно учитывая вот это: ... Если я скажу 'меня смущает' это тебя не устроит, я правильно понимаю? =) (*) legacy: здесь - любой код, время написания которого меньше либо равно времени выхода какой-либо версии como. (**) 'имен' - не указано каких - значит всех.
Приведи, пожалуйста, _свои_ аргументы. Не просто "Имхо", а те аргументы которые тебе не даю сделать 'новый тип'.
причем тут не дают? Плодить типы не охота, и макрос писать тоже неохота (IntelliSense туго с ними работает) ну вот пример: Код (Text): class thread1 : public thread { public: void on_process() { /* [body] */ } }my_thread; а вот это говорит мне, что my_thread - это объект единичного типа: Код (Text): class : public thread { public: void on_process() { /* [body] */ } }my_thread; так же мне нравится к примеру использовать параметры (microsoft'овская спецификация).
nop_ Да я не спорю, просто приходится адаптировать думалку к компилерам, на которых ведется разработка, а это, как правило, не comeau Поэтому, чтобы не переадаптировать ее (думалку) каждый раз - я выработал некий внутренний морально-этический стандарт, который значительно строже чем iso/iec В цепепе вообще можно делать много чего лишнего, причем большая часть сохраняется исключительно из соображений совместимости. ИМХО. Я не стандарт имею ввиду, а реализацию. Посмотри в любой объектник и увидишь там extern'ами все объекты из безымянных namespace'ов, имена которых генерятся так, как если бы они были объявлены в namespace'е с неким уникальным именем. Но никто не мешает подсмотреть эти имена вручную и слинковаться с таковыми опять-таки вручную. Это я и называю грязным хаком. Правда после перекомпиляции скорее всего придется переподсматривать. Устроит Более того, меня это тоже смущает. Но так есть. Не берусь утверждать, на каких именно компилерах, ибо не помню. Но это легко проверить, если не лень.