Неправильное разрешение имени, когда родительский и внутренний класс имеют одно и то же имя

У меня странный случай с Visual Studio 2003. По вполне законным причинам у меня следующая иерархия:

class A {};

class B : public A {
public:
    class A {};
};

class C : public B::A {};

То есть у меня есть внутренний класс с тем же именем, что и родитель внешнего класса. Когда C пытается наследовать от B::A, Visual Studio считает, что я указываю на родительский класс A, а не на вложенный класс внутри B. GCC, кажется, разрешает версию внутреннего класса, как я и ожидал

Это ошибка Visual Studio 2003 или я что-то не так делаю? Есть ли обходной путь (кроме обновления Visual Studio)?


person Michael Mrozek    schedule 17.08.2012    source источник
comment
Visual C++ 2003 был выпущен девять лет назад. Было бы целесообразно обновить по очень многим причинам.   -  person James McNellis    schedule 17.08.2012
comment
@JamesMcNellis Если бы я отвечал за эти вещи, мы бы давно обновились, но, к сожалению, я не   -  person Michael Mrozek    schedule 17.08.2012


Ответы (3)


Да, это похоже на ошибку VS2003. Обходной путь прост - используйте typedef, он работает следующим образом:

class A { public: int x; };
class B : public A { public: class A { public: int y; }; }; 

typedef B::A BA;

class C: public BA {};

void f()
{
   C cc;
   cc.y = 0;
}
person Rost    schedule 17.08.2012

Это выглядит как ошибка в Visual C++ 2003. При использовании Visual C++ 2012 B::A правильно называет вложенный класс A, а не базовый класс A.

person James McNellis    schedule 17.08.2012
comment
Что касается обходного пути, я не знаю: дизайн довольно сомнительный. Я бы переименовал вложенный класс. Если бы у меня был установлен Visual C++ 2003, я бы попробовал посмотреть, что происходит, но я не использовал Visual C++ 2003 несколько лет. - person James McNellis; 17.08.2012
comment
Я был глуп и не проверил свой упрощенный пример; оказывается неправильно. Обновлённый воспроизводит проблему - person Michael Mrozek; 17.08.2012

Это похоже на ошибку VS,
я не знал, спасибо за публикацию.
Я думаю, что обходным путем будет шаблон SafeInherit. Я не знаю, какое имя будет лучше.

template <typename T>
struct SafeInherit{
  typedef T Type;
};

class B : public SafeInherit<A>::Type {
  public:
  class A {};
}
person Neel Basu    schedule 17.08.2012