Поиск имен вложенных классов с наследованием - PullRequest
9 голосов
/ 12 августа 2011

Гарантированно ли это работает:

struct A
{
  struct Gold {};
};

struct B : public A
{
  typedef Gold BaseGold;
  struct Gold {};
};

struct C : public B
{
  typedef Gold BaseGold;
  struct Gold {};
};

static_assert(is_same<B::BaseGold, A::Gold>::value, "Not the right treasure!");
static_assert(is_same<C::BaseGold, B::Gold>::value, "Not the right treasure!");

Кажется, работает на VS2010.Очевидно, что он опирается на тонкие правила поиска порядка / имени декларации, поэтому мне было интересно, что говорит стандарт по этому вопросу ...

Ответы [ 2 ]

8 голосов
/ 12 августа 2011

Неопределенное поведение.

3.3.7 / 1

Следующие правила описывают область имен, объявленных в классах:

2) Имя N используетсяв классе S должен ссылаться на то же объявление в его контексте и при повторной оценке в завершенной области действия S. Никаких диагностических данных для нарушения этого правила не требуется.

1 голос
/ 12 августа 2011

Поскольку цитаты еще не было, я разыгрываю ваш пример:

И gcc 4.5.1, и Clang 3.0 принимают код, как показано ниже.

Теперь нам просто нужно, чтобы кто-то нашел авторитетный ответ. Хотя Clang, gcc и VC ++ согласны (хотя не , что часто), кажется, что это задумано.

Вкл. Идеон (4.5.1):

#include <utility>

struct A
{
  struct Gold {};
};

struct B : public A
{
  typedef Gold BaseGold;
  struct Gold {};
};

struct C : public B
{
  typedef Gold BaseGold;
  struct Gold {};
};

static_assert(std::is_same<B::BaseGold, A::Gold>::value, "Not the right treasure!");
static_assert(std::is_same<C::BaseGold, B::Gold>::value, "Not the right treasure!");

Вкл. Звон :

#include <stdio.h>

template <typename T, typename U>
struct is_same { enum { value = false }; };

template <typename T>
struct is_same<T,T> { enum { value = true }; };

struct A
{
  struct Gold {};
};

struct B : public A
{
  typedef Gold BaseGold;
  struct Gold {};
};

struct C : public B
{
  typedef Gold BaseGold;
  struct Gold {};
};

int main() {
  if (!is_same<B::BaseGold, A::Gold>::value) {
    printf("oups");
  }
  if (!is_same<C::BaseGold, B::Gold>::value) {
    printf("oups");
  }
}

Выход Clang (как и ожидалось):

define i32 @main() nounwind readnone {
entry:
  ret i32 0
}
...