Вот-с, столкнулся с такой штукой, при совпадении имени параметра шаблона (здесь это B) с именем унаследованного локального класса VC выбирает локальный класс, а GCC — параметр. Это более или менее минимальный пример, на практике у меня boost_assert(boost_type_traits(B)) обломался при портировании с gcc (надо же, пригодился всякий пожарный ассерт).
Вопрос классический и по большому счету чисто теоретический: кто виноват и что делать?
Если уже обсуждалось (что наверняка), дайте ссылку, найти не получилось, слишком много мусора по ключевым словам.
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re: Конфликт имен: аргумента шаблона и у унаследованное
MescalitoPeyot:
MP>Вот-с, столкнулся с такой штукой, при совпадении имени параметра шаблона (здесь это B) с именем унаследованного локального класса VC выбирает локальный класс, а GCC — параметр.
Класс A::B — не локальный, а вложенный. В выражении B::f к B применяется обычный unqualified name lookup. При таком поиске искать имя B в зависимом базовом классе не разрешается:
14.6.2/3:
In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
MP>Вопрос классический и по большому счету чисто теоретический: кто виноват
В данном случае VC++ не соблюдает требования стандарта.
MP> и что делать?
Поменять название параметра шаблона?
Re[2]: Конфликт имен: аргумента шаблона и у унаследованное
Здравствуйте, Masterkent, Вы писали:
M>MescalitoPeyot:
M>14.6.2/3: M>In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
Спасибо.
M>Поменять название параметра шаблона?
Так и сделал, поэтому и пишу — вопрос теоретический. Однако вообще довольно стремный баг.
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[2]: Конфликт имен: аргумента шаблона и у унаследованное
M>Класс A::B — не локальный, а вложенный. В выражении B::f к B применяется обычный unqualified name lookup. При таком поиске искать имя B в зависимом базовом классе не разрешается:
А вы бы не могли пояснить, почему к Type-dependent expression B::f применяется именно unqualified name lookup?
Re[3]: Конфликт имен: аргумента шаблона и у унаследованное
Bender Bending Rodriguez:
BBR>А вы бы не могли пояснить, почему к Type-dependent expression B::f применяется именно unqualified name lookup?
Тут речь конкретно про имя B. Формального определения "unqualified name" я в стандарте не встречал. Можно людей из комитета по этому поводу потрясти. То, что в данном случае для B применяется unqualified name lookup, можно установить методом исключений. В качестве postfix-expression в некоем вызове функции имя B не используется, значит, ADL (3.4.2) тут не применяется. Qualified name lookup (3.4.3) здесь не применяется, т.к. непосредственно перед B нет ::. elaborated-type-specifier (3.4.4) здесь не образуется. Явного class member access (3.4.5), образуемого оператором . или ->, здесь тоже нет. К using-directives and namespace aliases (3.4.6) данная конструкция не относится. Остаётся только поиск по правилам ordinary unqualified name lookup (3.4.1).
Re[3]: Конфликт имен: аргумента шаблона и у унаследованное
Здравствуйте, Bender Bending Rodriguez, Вы писали:
BBR>Здравствуйте, Masterkent, Вы писали:
M>>Класс A::B — не локальный, а вложенный. В выражении B::f к B применяется обычный unqualified name lookup. При таком поиске искать имя B в зависимом базовом классе не разрешается:
BBR>А вы бы не могли пояснить, почему к Type-dependent expression B::f применяется именно unqualified name lookup?
Потому что тот, кто пишет код шаблона:
template<class B>
class D
{
void memfunc(void)
{
B::f();
}
};
... по интуитивной логике ожидает вызова функции f() из того класса, которым типизирован шаблон, а не из чего-то другого под тем же именем B, даже если это базовый класс.
И если пишет, как в исходном примере:
template <class B>
struct D : public B
{
static void g()
{ B::f(); }
};
... то ожидает, что это вызов f() базового класса, которым типизирован шаблон, а не чето-то другого под именем B, даже если это что-то есть в этом базовом классе.
_>... по интуитивной логике ожидает вызова функции f() из того класса, которым типизирован шаблон, а не из чего-то другого под тем же именем B, даже если это базовый класс.
Когда базовый класс non-dependent, он вполне может скрыть параметр шаблона:
struct B
{
static void f() {}
};
template <class B>
struct D : ::B
{
static void g()
{
B::f(); // B - это injected-class-name базового класса ::B
}
};
int main()
{
D<int>::g();
}
Тут уже GNU C++ 4.5.0 нарушает стандарт, трактуя B как параметр шаблона.
14.6.1/7:
In the definition of a class template or in the definition of a member of such a template that appears outside of the template definition, for each base class which does not depend on a template-parameter (14.6.2), if the name of the base class or the name of a member of the base class is the same as the name of a template-parameter, the base class name or member name hides the template-parameter name (3.3.7).
Re[5]: Конфликт имен: аргумента шаблона и у унаследованное