[CFR] B@N@N как минимум, версии SDL2 и VGUI несовместимы с ксашевскими. Ещё сервер завязан на стимовских интерфейсах. На FWGS не заводится, на ванилле - тем более.
Вальва с этим внезапным обновлением голдсорса подложила всем Геганцкую Свенью™
Напоминаю, что это делалось ради стим-бокса, который в итоге так и не вышел, портирование игр на линукс закончилось пшиком - линуксоиды не захотели за это платить. Зато мы получили изумительный несовместимый голдсорс, который для своей работы требует теперь FBO, т.е. минимум GeForce 8xxx. Так мало было виндовых функций проброшенных в клиентку.
Теперь туда еще и SDL примотали. И все носятся с этим обновлением и причитают - о боже, нам срочно нужна такая халфа.
Для понимания того, что собой представляют, ну как минимум старые компиляторы (да и новые зачастую тоже) С\С++, приведу вам вот какой факт: эти компиляторы по сути - продвинутая версия интерпретаторов ассемблера. Только ассемлеровские листинги просто конвертятся в опкоды процессора, а смысл этой замуты в то, что опкоды для разных архитектур отличаются, а во вторых приятнее всё же читать команды push, mov нежели просто номера опкодов - глазу удобнее.
Так вот Си в большей степени, а С++ в меньшей степени являются точно такими же интерпретаторами, которые помнят объявленные переменные.
Генерация опкодов происходит прямо по факту чтения очередного операнда, ну в некоторых случаях компилятор сам втыкает условия и goto, например в циклах или свитчах. С парсингом классов чуть похитрее - там двухпроходной цикл, сначала парсим члены класса, пропуская тела функций, объявленных внутри декларации класса, потом парсим только тела функций.
Функции класса, объявленные вне его тела парсятся в обычном режиме.
Самая сложная замута с шаблонами, их вообще нельзя парсить на момент их объявления, поэтому компилятор сохраняет их исходный текст в укромное место и начинает парсить только когда предвидится реальный шаблонный вызов, из-за чего ошибки шаблонов сыплются чуть ли на этапе линковки и немало удивляют юзера. Вообще я так понимаю этот костыль с шаблонами, Страуструп прикрутил по многочисленным просьбам телезрителей чуть ли не в самом конце разработки. Вот они и получились такие неудалые. Впрочем более современные компиляторы, вроде как со стандартная С++11, уже так не делают, они все опкоды сохраняются в какие-то локальные массивы, отчего там и ошибки информативнее и возможны некоторые конструкции, которые не работали на стандарте С99. Ну об этом можно в Вики почитать.
Добавлено 28-05-2022 в 17:23:
Кстати эти современные компиляторы далеко не факт что спровляются лучше старых, но вот памяти жрут однозачно больше, и при этом компилируют дольше. Ну это так, к слову. Направление эволюции вполне естественное.
Вообщем вот какая у меня нехорошая вещь получилась. Поскольку это всё же виртуальная машина, а не настоящий С++, у меня не получилось сделать из компилятора нормальный вызов виртуального деструктора. Потому что опирается не на участок памяти, по которому идёт переход на виртуальную таблицу, а на тот тип, который сунули в указатель delete. И соответственно если вызов деструктора делает компилятор, то без разницы виртуальный он или нет - правильность его вызова напрямую зависит от типа указателя, а ведь смысл виртуальных деструкторов в том и заключается чтобы правильно работать независимо от типа входных данных. Хорошо, я выбросил этот вызов из компилятора и конструктивно объединил вызов деструктора в рантайме с высвобождением памяти. Это прекрасно работает абсолютно в любом случае, т.к. VM располагает всей необходимой информацией.
Но вылезла другая проблема, блин! Теперь оно ВСЕГДА работает правильно, независимо от того, виртуальный деструктор или нет. Само по себе это проблемы не представляет, поскольку вызов идёт именно правильный.
Проблема в другом. Если кто-то напишет код на моей VM без виртуальных деструкторов, а потом решить его перенести на С++, оно перестанет правильно работать. Хотя в сущности поправить дело будет несложно, достаточно будет прописать virtual у деструктора базового класса.
Помнится мне, что когда я меню разрабатывал у меня там тоже кошмар начался, а прописал virtual и помогло. Т.е. технически проблемы нет, просто будет вот такая особенность языка. Деструкторы всё равно не могут быть перегружены, скорее виртуальный деструктор - это костыль для самого С++, нежели реальная необходимость.
Дядя Миша писал: виртуальный деструктор - это костыль для самого С++, нежели реальная необходимость.
Виртуальный деструктор предназначен не для переопеределения, а для того, чтобы правильно удалять класс через указатель на базовый класс. Почему не все деструкторы по дефолту виртуальные? Чтобы не создавать vtbl там, где она не особо нужна. Главный принцип С++ "ты платишь только за то, что используешь", и это один из примеров его применения.
XaeroX писал: Виртуальный деструктор предназначен не для переопеределения, а для того, чтобы правильно удалять класс через указатель на базовый класс
Я понимаю. В моей реализации эта штука оказалась лишней. Она будет работать, её можно использовать, но ничего кроме выполнения лишних инструкций она не повлечёт.
Цитата:
XaeroX писал: Чтобы не создавать vtbl там, где она не особо нужна.
Ну у меня чуть хитрее сделано. Вместо vtable выделяется хэндл с номером метаинформации, который заполняется в рантайме при вызове конструктора.
А vtable находится уже в самой метаинформации и не дублируется в экземпляре класса, как в С++. Т.е. экземпляр класса имеющий непосредственный доступ к метаинформации увеличивается в размерах всегда на 4 байта. Множественное наследование я делать не буду, ну его на.
Опять таки, динамически созданные экземпляры класса всегда имеют доступ к метаинформации, т.е. это скорее актуально для экземпляров, созданных на стеке и в глобальной куче.
Ну что же, теперь, когда я достаточно понаторел в разработке С++ совместимого языка, я могу вам наконец-то рассказать, за что же его все так ругают и почему это с ним произошло в отличие от того же Си.
Всё дело в том, по-видимому, что Страуструп писал его в молодости и был увлекающейся натурой. То есть он придумывал какую-то фичу, которую можно было реализовать в рамках препроцессора Си и тут же её внедрял.
Как правило это давало какие-то новые возможности и открывало для программиста новые удобства. Но порождало комбинаторный взрыв, который в свою очередь разрушал целостность поведения, порождая UB.
Как когда-то написал Боресков в своей статье - откройте любую книгу по С++, о чём там будет написано в первую очередь? "Как не надо делать!".
То есть довольно много таких проблематичных мест на самом деле, из-за чего невозможно догадываться о поведении языка в целом, а желательно уточнять в справочнике, если вдруг что-то не заработало. Опытный программист просто их все знает наизусть и в ногу себе не стреляет.
Новичок же пытается экстрполировать полученный опыт но весь язык и очень часто получает граблями по носу. Это основная претензия, так сказать. В какой-нибудь Яве или СиШарпе перетянули в обратную сторону - постарались исключить вообще всё, что могло вызывать малейшие проблемы, из-за чего эти языки обновляются с пугающей периодичностью - туда постоянно добавляют то, чего не хватает юзерам. И то и другое - очевидно крайности. Я попытаюсь сделать свой язык максимально близким по синтаксису и парадигме к С++, но при этом лишив его пугающих неоднозначностей и UB, насколько это в моих силах. Чтобы никто не смог выстрелить себе в ногу.
Скрытый текст:
Этот текст скрытый. Вы должны оставить хотя бы одно сообщение в теме, чтобы его увидеть.
Хочу вам на наглядном примере показать, почему в перегрузке функций, к сожалению нельзя опираться на то что функция возвращает. Иными словами нельзя иметь перегруженные функции, у которых меняется только тип возврата
C++ Source Code:
int get( void );
float get( void );
Собственно, почему это не работает. Всё дело в поддержке вызова аргументов в виде других функций. Ну то есть чтобы не писать
C++ Source Code:
int a = foo();
bar( a );
Мы можем просто написать
C++ Source Code:
bar( foo() );
Это удобно, но мы попадаем в логическую ловушку. Для того чтобы определить перегруженную только по возвратному типу функцию foo, мы сперва должны узнать какой тип аргумента принимает bar, а если bat перегружен тоже, то мы никаким чудом не сможем узнать какую функцию выбрать из foo - ведь мы же еще не выбрали bar, а bar мы не выберем, поскольку не можем выбрать foo. Замкнутый круг.
Собственно почти все ограничения С++ относятся именно вот к таким логическим ловушкам. Именно поэтому они и не исправляются в новых редакциях языка. Потому что это невозможно в принципе.
Запрещать такую форму записи тоже не вариант - ведь это очень удобно.
Приходится выбирать чем пожертвовать.
Добавлено 08-06-2022 в 10:28:
Опять же, несмотря на строгую типизацию, С++ унаследовал от Си довольно много неявных преобразований. Например, преобразование к void * всегда неявное. Точно так же конверсия базовых типов выполняется неявно, хотя компилятор и сыплет предупреждениями, типа 4244, но их затыкают в первую же очередь. А в новых версиях С++ они возможно на четвертом уровне и отключены по умолчанию.
Ну чтож, замутил я перегрузку функций, прямо как в С++. Самым поганым оказалось необходимость написания функции с тысячами if-else, прямо как ФиЭктра любит. Вот к сожалению никак это в табличку не свести.
Но я смотрю вам неинтересно всё что я пишу по С++? То ли вы так хорошо язык знаете, то ли вам просто неинтересны эти подробности.