MSVC: ERROR (duplicate COMDAT) или анонимные классы?

Тема в разделе "LANGS.C", создана пользователем Arthur, 26 май 2009.

  1. Arthur

    Arthur New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2007
    Сообщения:
    494
    Доброе время суток! Тут недавно попытался использовать больше одного анонимного класса на MSVC++ 2005 Express Edition, и тут же мне linker выдает такой фокус:

    вот пример:
    Код (Text):
    1. template<int n>
    2. class A
    3. {
    4. public:
    5.     A()
    6.     {
    7.         printf("A.ctor(%i); \r\n", n);
    8.     }
    9. };
    10.  
    11. class : public A<1> {}A1;
    12.  
    13. class : public A<2> {}A2;
    Такой же код, только под MSVC++ 2008 Express Edition SP-1 RUS работает нормально.
     
  2. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    "Нормальная" работа этого кода - это такой же "фокус", как и возникновение сообщения об ошибке. Приведенный код не является валидным с точки зрения С++ (см. стандарт, 7.3).
     
  3. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Извиняюсь, не "7.3" а "7/3"
     
  4. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    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 пропадает.
     
  5. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Действующий стандарт - ISO/IEC 14882:2003

    Хотел написать "7/3", но это тоже не то, там все несколько сложнее и завязано на linkage. В некоторых контекстах такой синтаксис допустим, в некоторых - нет.

    Это говорит только о том, что "MSVC 2008 нормально работает. gcc 4.3 тоже". и больше ни о чем. msvc, например умеет биндить временные объекты к неконстантной ссылке. Только из этого не следует что в С++ есть такая возможность.
     
  6. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    nop_
    Де-юре, разве что. Лучше рассчитывать на старый добрый 98-й.

    Ниче не понял :dntknw: что есть 7/3 ???

    Дык, стандартом-то не сильно скомпилируешь :) поэтому все сводится к тому, работает или нет на конкретном компиляторе. long long тоже стандартом вроде не одобрен, тем не менее, покажите мне компилятор, в котором оный не поддерживается :)
    Я хочу сказать, что эта конструкция в принципе не противоречит стандарту. Но там где шаблоны - всегда неприятности, здесь и стандарт и компилеры просто не успевают за фантазией програмеров :):):)
     
  7. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    "Старый добрый" уже не имеет статуса стандарта, хотя отличий там совсем немного, т.к. он содержит в основном исправления.

    Ниче не понял :dntknw: что есть 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):
    1. class : A<1> {} A1; // error
    2.  
    3. static class : A<2> {} A2; // ok
    4.  
    5. void f()
    6. {
    7.   class : A<3> {} A3; // ok
    8. }
    Шаблоны здесь в общем-то ни при чем.
     
  8. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    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):
    1. template <int a, int b>
    2. inline Fix<a+b> operator *(const Fix<a>& x, const Fix<b>& y)
    3. {
    4.     return Fix<a+b>(x.val * y.val);
    5. }
    От такого невинного по нынешним временам кода этот с позволения сказать компилер скрючило и он издох в мучениях. И я окончательно перебрался на Watcom. :):):)
    [/offtop]
     
  9. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    В global scope это не должно компилироваться.

    Что есть 'статичность'?

    Связывание имеет смысл для имен, имена вводятся объевлением/определением - для этого требуется имя типа объявляемого объекта. Вероятно я некорректно выразился, но именно я имел ввиду.

    Как это кореллирует с наличием/отсутствием связывания?

    Если объект(такой как 'A1' например) определен в namespace scope (сюда в том числе входит и global scope) то (без дополнительных условий) это значит что он может быть доступным из других едениц компиляции(TU). Для этого требуется 'extern' объявление. А для этого требуется имя типа, которого у нас нет. + на момент компиляции TU с определением 'A1' компилятор ничего не знает о том, будет ли где-нибудь в других TU необходимость в 'extern' объявлении, да и в принципе не может знать, т.к. линковка с другими TU может осуществляться намного позднее. Поэтому ему _необходимо_ имя типа определенного объекта. Определение такого объекта в block scope (теле функции), как и определение его с квалификатором 'static' снимает необходимость наличия имени в связи с тем, что в других TU он не будет (и в принципе не может быть) востребован.

    Это действительно так.
     
  10. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    nop_
    Кто сказал?

    static'ность :) то есть внутреннее связывание.

    Я, в принципе, понял, что имеется ввиду :)

    Да понял я , понял. Я даже готов согласится. Мутное это дело - раздельная компиляция и все что с ней связано.

    У нас нет, а у компилятора есть. Не пугают же никого глобальные переменные в неименованных namespace'ах. Не вижу принципиальной разницы. По стандарту, еще раз повторю, исключительным случаем является только глобальное неименованное union (ну, это понятно почему).
     
  11. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    почему? )
     
  12. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    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). Это является требованием. О каком "исключении" ты говоришь?
     
  13. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    nop_
    Это один их многих. Более того, я не знаю ни одного проекта на нем созданного.

    Я протестую, ваша честь! Это мелочные придирки :)

    Еще раз: чем это отличается от имен в неименованных namespace'ах? linkage у них external? Он самый. По крайней мере в известных мне компилерах. Их других единиц компиляции к ним доступ есть? Фиг. Хотя "грязным хаком" сделать можно. И кого это смущает?

    Это я напутал, если честно, это требование немного в другом случае работает. Да и смысл union'а совсем другой.

    Но в общем и целом я согласен, фиговая конструкция, ИМХО. Будем считать, меня ты убедил. Осталось убедить разработчиков компиляторов :) А до тех пор придется учится самим не простреливать себе ногу. Черт, неужели кому-то без этого скучно? :lol: :lol: :lol:
     
  14. Arthur

    Arthur New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2007
    Сообщения:
    494
    вот этого не надо делать :)

    Хоть на 2008 работает и то хорошо :)

    Нет, суть была в чем - я создаю некую библиотеку (в данном случае, стандарт Си++ меня не интересует, так как библиотека полностью под windows, и переносимость хотелось в рамках msvc++ компиляторов), там есть классы с виртуальными функциями, т. е. достаточно унаследоваться от этого класса и перегрузить функцию и вуаля. Но вот создавать новый тип, как-то не очень, более наглядно и красивее (ИМХО) выглядит именно анонимные классы. Вот и все. А веревку достаточной длины что бы прострелить себе ногу, кхм, потянул тогда когда решил программировать на C/C++ :)
     
  15. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    а) исходный код этот компилятор не компилирует.

    б) на прктике - это единственный компилятор, который постулирует (и не просто так!) 100% standard conformance. Я не знаю наколько это актуально (особенно на _этом_ форуме) для большинства, но для меня соответствие (кода) стандарту - хм... это прсто _должно_ быть... я не знаю как сказать по другому. workaround's, да, они бывают...

    Это не значит что их не существует, ведь правда? =) Да и впорос на самом деле стоит по другому - какой процент проектов способен откомпилировать тот же comeau. Для legacy (*) - 99% ноль (без шаманства с флагами, etc.), по крайней мере, противоположных примеров (кроме того 1-го процента) я не знаю... Хорошо это или плохо - по этому поводу я спорить не готов.

    Какое интересное утверждение. хотелось бы увидеть ссылку на стнадрт. Особенно учитывая вот это:

    ...
    Если я скажу 'меня смущает' это тебя не устроит, я правильно понимаю? =)

    (*) legacy: здесь - любой код, время написания которого меньше либо равно времени выхода какой-либо версии como.
    (**) 'имен' - не указано каких - значит всех.
     
  16. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Приведи, пожалуйста, _свои_ аргументы. Не просто "Имхо", а те аргументы которые тебе не даю сделать 'новый тип'.
     
  17. Arthur

    Arthur New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2007
    Сообщения:
    494
    причем тут не дают? Плодить типы не охота, и макрос писать тоже неохота (IntelliSense туго с ними работает) ну вот пример:

    Код (Text):
    1. class thread1 : public thread
    2. {
    3. public:
    4.    void on_process()
    5.    {
    6.      /* [body] */
    7.    }
    8. }my_thread;
    а вот это говорит мне, что my_thread - это объект единичного типа:
    Код (Text):
    1. class : public thread
    2. {
    3. public:
    4.    void on_process()
    5.    {
    6.      /* [body] */
    7.    }
    8. }my_thread;
    так же мне нравится к примеру использовать параметры (microsoft'овская спецификация).
     
  18. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    nop_

    Откуда у тебя столько терпения? )))
     
  19. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    nop_
    Да я не спорю, просто приходится адаптировать думалку к компилерам, на которых ведется разработка, а это, как правило, не comeau :) Поэтому, чтобы не переадаптировать ее (думалку) каждый раз - я выработал некий внутренний морально-этический стандарт, который значительно строже чем iso/iec :)
    В цепепе вообще можно делать много чего лишнего, причем большая часть сохраняется исключительно из соображений совместимости. ИМХО.
    Я не стандарт имею ввиду, а реализацию. Посмотри в любой объектник и увидишь там extern'ами все объекты из безымянных namespace'ов, имена которых генерятся так, как если бы они были объявлены в namespace'е с неким уникальным именем. Но никто не мешает подсмотреть эти имена вручную и слинковаться с таковыми опять-таки вручную. Это я и называю грязным хаком. Правда после перекомпиляции скорее всего придется переподсматривать.
    Устроит :) Более того, меня это тоже смущает. Но так есть. Не берусь утверждать, на каких именно компилерах, ибо не помню. Но это легко проверить, если не лень.