Как сделать копирование-вставку дружественным typedef для OuterClass в C ++ 11?

0

Я заметил, что ручное обозначение typedef на OuterClass слишком дорого и иногда приводит к смущающим ошибкам. Поэтому я решил создать дружественный typedef для копирования-вставки на OuterClass. Вот что я получил:

#include <type_traits>

struct A{
  typedef A NextOuterClass;
  typedef A SelfClass;
  struct B{
    typedef NextOuterClass OuterClass;
    typedef B NextOuterClass;
    typedef B SelfClass;
    struct C{
      typedef NextOuterClass OuterClass;
      typedef C NextOuterClass;
      typedef C SelfClass;
    };
  };
};

#define CHECK(OWNER,TYPE)\
  static_assert(\
  std::is_same<OWNER::TYPE::OuterClass,OWNER>::value,\
  #OWNER"::"#TYPE" - not ok"\
);
CHECK(A,B);
CHECK(A::B,C);
#undef CHECK

int main(){return 0;}

Он работает достаточно хорошо, но не всегда:

#include <type_traits>

struct I{
  typedef I NextOuterClass;
  typedef I SelfClass;
};

struct D{
  typedef D NextOuterClass;
  typedef D SelfClass;
  struct E:public I{
    typedef NextOuterClass OuterClass; // NextOuterClass == I::NextOuterClass
    typedef E NextOuterClass;
    typedef E SelfClass;
    typedef I ParentClass;
  };
};

#define CHECK(OWNER,TYPE)\
  static_assert(\
  std::is_same<OWNER::TYPE::OuterClass,OWNER>::value,\
  #OWNER"::"#TYPE" - not ok"\
);
CHECK(D,E); // D::E - not ok
#undef CHECK

int main(){return 0;}

Если я удалю "typedef я NextOuterClass;", тогда он будет работать, но это плохое решение, потому что класс "I" также может иметь подклассы:

#include <type_traits>

struct I{
  typedef I NextOuterClass;
  typedef I SelfClass;
  struct G{
    typedef NextOuterClass OuterClass;
    typedef G NextOuterClass;
    typedef G SelfClass;
  };
};

struct D{
  typedef D NextOuterClass;
  typedef D SelfClass;
  struct E:public I{
    typedef NextOuterClass OuterClass; // NextOuterClass == I::NextOuterClass
    typedef E NextOuterClass;
    typedef E SelfClass;
    typedef I ParentClass;
  };
};

#define CHECK(OWNER,TYPE)\
  static_assert(\
  std::is_same<OWNER::TYPE::OuterClass,OWNER>::value,\
  #OWNER"::"#TYPE" - not ok"\
);
CHECK(I,G);
CHECK(D,E); // D::E - not ok
#undef CHECK

int main(){return 0;}

Я попытался использовать функции "private" и "template", но до сих пор не достиг желаемого поведения.

В С++ 11 или С++ 14 есть надежный способ найти OuterClass?

Было бы неплохо иметь такие вещи здесь:

std::get_outer_class<T>::type
std::is_nested_class<T>::value
Теги:
c++11
code-generation
rtti
visual-c++-2010

1 ответ

1

Ваш пример плохо сформирован:

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

  1. Потенциальная область имени, объявленного в классе, состоит не только из декларативного региона, следующего за точкой имен декларации, но также и из всех тел функций, элементов или нестационарных элементов элементов нестатических данных и аргументов по умолчанию class (включая такие вещи во вложенных классах).
  2. Имя N используемое в классе S должно ссылаться на одно и то же объявление в его контексте и при повторной оценке в завершенной области S. Диагностика не требуется для нарушения этого правила.
  3. Если переупорядочивание объявлений-членов в классе дает альтернативную действительную программу в соответствии с (1) и (2), программа плохо сформирована, диагностика не требуется.

Ваш подход зависит от имени NextOuterClass ссылающегося на разные вещи в разных точках определения вложенного класса. Именно это и запрещает (2).

  • 0
    Я понимаю, что это скорее комментарий, чем ответ, но для объяснения потребовалось слишком много текста, чтобы уместиться в комментарии.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню