Это правило, очевидно, не распространяется на вложенные классы. Рассмотрим следующий рабочий пример:
Код: Выделить всё
struct C { // #1
// Forward declaration only
struct A; // #2
struct B {
// Pointer declaration is allowed with incomplete type
A* a;
int foo() {
// Member requires complete definition of A
return a->value;
}
};
// Complete definition of A given after B
struct A {
int value;
};
// Members and constructor
A a; B b;
C(int x) : a{x}, b{&a} {}
};
int main() {
C c{42};
return c.b.foo(); // returns 42
}
Дословное удаление определений A/B из включающей структуры C (т. е. удаление #1) приводит к ожидаемой ошибке о неправильном использовании неполного типа. Полное удаление предварительного объявления (т. е. удаление #2) приводит к ошибке «неизвестное имя типа «A».
Это не теоретическая проблема: библиотека Open Motion Planning Library, важная библиотека робототехники, использует этот шаблон в нескольких местах для определения компараторов для приоритетного порядка очереди. (Чтобы увидеть более полные примеры, найдите репозиторий MotionCompare).
Итак, вопрос: почему это компилируется? Это неясная стандартная функция вложенных типов или обычная ошибка компилятора? Изменилась ли достоверность этой конструкции по мере развития языкового стандарта?
РЕДАКТИРОВАТЬ: Этот связанный вопрос имеет аналогичный ответ, но это не тот же самый вопрос. В частности, эти двое не могли быть идентифицированы как дубликаты, не зная ответа. Этот вопрос касается явного предварительного объявления родственного класса; другой касается неявного предварительного объявления родительского класса. Тот факт, что в обеих ситуациях применяются одни и те же правила поиска имени, не был очевидным. Кроме того, поскольку другой вопрос явно не ссылается на предварительное объявление или родственные классы, маловероятно, что кто-то ищет ответ в этих случаях.
Подробнее здесь: https://stackoverflow.com/questions/797 ... forward-de
Мобильная версия