ссылаться на еще не объявленные классы/структуры?
struct A {
B* b;
};
struct B {
A* a;
};
Почему разработчик должен предварительно объявлять структуру для того чтобы ее использовать при объявлении поля? Почему компилятор не может отложить вывод типа пока оно не запарситься (ну или автоматически генерировать struct Name; объявление каждый раз когда встречает поле с неизвестным типом) ?
struct B; //why???
struct A {
B* b;
};
struct B {
A* a;
};
Кмк очень обскурные ошибки будут. Комилятор компилирует tu, что если в вашем tu B никогда не встретился? И как это фиксить? Куда его инклудить?
В таком случае можно забить хрен, просто sizeof(void*) бесполезных данных будет занимать
>> почему нельзя при объявлении полей класса ссылаться на еще не объявленные классы/структуры? Чтобы не провоцировать мистические неуловимые ошибки из-за того, что неявно пометили B как тип, а чуть ниже он вдруг стал переменной или шаблоном, или чем-то ещё
А что если B например вызывает инстанцирование темплейта у которого есть сайдэффекты? Мы тогда все это пропустим
Имхо это наследие строго однопроходной Сишки, где компилятор не мог "вернуться" назад и что-то додумать. В C++ компилятор не однопроходной (те же классы), но наследие тянется
>> Почему разработчик должен предварительно объявлять структуру для того чтобы ее использовать при объявлении поля? Например, потому что это не всегда структура и ваш вопрос перекликается с этим
Как ты сослаться можешь на параметр шаблона/переменную? Т.е. не на тип? B* b; это +- однозначная запись
ну вот во время парсинга мы генерируем объявления struct Name; для полей с неизвестными типами и добавляем во временный список а когда запарсили весь translation unit смотрим были ли объявлены типы из этого временного списки и если нет то выдаем ошибку. В чем проблема?
using B = foo<bar>;
Это — однозначная. А строкой ниже объявление переменной с тем же именем: B* b; int B; И что у нас получится? А главное, @xbgnx? B — из какого оно скоупа?
Чтобы компилятор понимал, что B - это тип. К тому же, форвард декларация явно указывает, где именно этот тип будет лежать. Могут быть совершенно разные случаи: namespace ns { struct B; } using namespace ns; // vs struct B; Если ещё и A будет лежать в неймспейсе, совсем беда.
foo<bar> это тип, не параметр шаблона или переменная
почему не переменная?
из того же скоупа из которого будет предварительное объявление типа перед классом где находится поле с неизвестным типом. То есть я хочу чтобы видя такую запись struct Some { ... SomeType* field; } где SomeType* это неизвестный тип (ранее не встречался) компилятор автоматически вставил бы дополнительную строчку с объявлением этого типа перед текущим классом struct SomeType; //вставленная компилятором строчка struct Some { ... SomeType* field; } и уже в конце парсинга TU компилятор выдал бы ошибку что SomeType это неизвестный тип если он так и не был объявлен Соответственно этот тип будет лежать в этом же скоупе TU (или глобальный неймспейс или как это называется) В чем проблема с таким подходом?
using namespace std; namespace A { namespace B { namespace C { namespace { struct Some { ... SomeType* field; }; }}}} В какой из 7(!) скоупов компилятор должен поместить декларацию SomeType?
Проблема в том, что вы хотите напрячь писателей компиляторов лишней работой ради неизвестно чего
если у нас есть конфликты имен то выдаем ошибку. Я про кейс когда имя типа поля на момент парсинга неизвестно но будет объявлено позже (то есть берем первое объявление которое встретится позже)
Ну я был бы рад не писать тонну forwarding declarations. Если бы компиляторописатели не напрягались, мы бы не увидели auto, концепты, модули...
struct A { struct B* b; } struct B { A* a; }; (и всё)
Зачем нужно то что вы перечислили понятно. А вот зачем ваши хотелки - нет
Чтобы с JS не переучиваться
Не работает если B в неймспейсе
Ха, оказыается так можно) Спасибо. Я тогда буду всегда объявлять поля со struct-префиксом и забуду про необходимость предварительно объявлять типы (когда пишешь всякие косвенно-рекурсивные структуры)
Естественно, компилятор не должен в угадайку играть
А auto, concepts, decltype чем не угадайки?
>> забуду про необходимость предварительно объявлять типы Рекомендую ещё раз открыть мою ссылку выше и понять, что это тупиковый подход. Декларации всегда должен предоставлять автор класса, и никогда не его пользователь
Конечно, кто будет переучиваться с JS на C++, чтобы получать меньшую зарплату
Я же сказал, чтобы не писать тупые forwarding declarations
То есть вам лень написать строчку и вы хотите, чтобы писатели компиляторов напряглись по этому поводу?
Дедам было лень писать for (std::vector<double>::iterator it = v.begin(); it != v.end(); ++it) { ... } но "это другое"?
Тут не надо ничего особо делать, тип для auto прямо в этом выражении есть.
с точки зрения читающего лучше чтобы сначало что то декларировалось, а потом использовалось
Обсуждают сегодня