Я заметил, что ручное обозначение 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
Ваш пример плохо сформирован:
3.3.7/1 Следующие правила описывают область имен, объявленных в классах.
- Потенциальная область имени, объявленного в классе, состоит не только из декларативного региона, следующего за точкой имен декларации, но также и из всех тел функций, элементов или нестационарных элементов элементов нестатических данных и аргументов по умолчанию class (включая такие вещи во вложенных классах).
- Имя
N
используемое в классеS
должно ссылаться на одно и то же объявление в его контексте и при повторной оценке в завершенной области S. Диагностика не требуется для нарушения этого правила.- Если переупорядочивание объявлений-членов в классе дает альтернативную действительную программу в соответствии с (1) и (2), программа плохо сформирована, диагностика не требуется.
Ваш подход зависит от имени NextOuterClass
ссылающегося на разные вещи в разных точках определения вложенного класса. Именно это и запрещает (2).