Здравствуйте, han2, Вы писали:
H>Привет, народ.
H>Поясните, плз, почему указанный ниже код сомпилируется в VC7.1, но не компилируется в VC9, выдывая ошибку C3200 (и другие):
H>
Жаль, что из примера не понятно, какую роль играет эта замысловатость типов — ведь aux::TrimUnused< Root, A >::Result — это просто Root.
А вообще, похоже на еще один глюк студии. Интересно, что проблема устраняется простым вынесением определения типа _BaseT за пределы класса D. Также ошибка уходит при отказе от наследования D от aux::TrimUnused< Root, A >::Result (он же Root).
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Жаль, что из примера не понятно, какую роль играет эта замысловатость типов — ведь aux::TrimUnused< Root, A >::Result — это просто Root.
Это редуцированный до случая с T[N]=0, где N=0, пример реального шаблона, используемого для организации линейного наследования классов.
R> ведь aux::TrimUnused< Root, A >::Result — это просто Root.
Соответственно, aux::TrimUnused< Root, A >::Result — это, на самом деле A< Root >
R>А вообще, похоже на еще один глюк студии.
Если это ошибка, то она также есть и в VC10, которая выдаёт ту же ошибку при компиляции этого кода.
R>Интересно, что проблема устраняется простым вынесением определения типа _BaseT за пределы класса D.
Да, так и есть, проверил. Значит, скорее всего, ошибка VC.
R>Также ошибка уходит при отказе от наследования D от aux::TrimUnused< Root, A >::Result (он же Root).
По указанной выше причине (организация рекурсивного линейного наследования классов) это сделать не возможно, разве что перейти на использование boost::mpl::inherit_linearly.
typedef aux::TrimUnused< Root, A >::Result _BaseT;
Итогом поиска имени A будет ::A<Root>::A из базового класса, которое скрывает глобальное ::A.
В C++03 14.6.1 p1 говорится, что
Like normal (non-template) classes, class templates have an injected-class-name (clause 9). The injectedclass-
name can be used with or without a template-argument-list. When it is used without a templateargument-
list, it is equivalent to the injected-class-name followed by the template-parameters of the class
template enclosed in <>.
Поэтому ::A<Root>::A становится ::A<Root>::A<Root>, что уже не может использоваться как аргумент для template template parameter, о чём, собсно, VC++ и рапортует. Чтоб осчастливить компилятор, достаточно вместо A использовать ::A