HLFX.Ru Forum
Показать все 188 сообщений этой темы на одной странице

HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- Флуд (https://hlfx.ru/forum/forumdisplay.php?forumid=11)
-- Заметки на полях (https://hlfx.ru/forum/showthread.php?threadid=5815)


Отправлено Дядя Миша 27-03-2022 в 14:02:

Заметки на полях

Я, как вы, должно быть знаете, в данный момент работаю над собственной виртуальной машиной для XashNT, которая будет использоваться для описания игровых объектов, меню и интерфейса редактора. Ну и может еще для чего-нибудь. Чтобы не плодить сущности, я решил сделать в этой машинке слегка ограниченный С++, который будет иметь большинство возможностей настоящего, но при этом выполняться в виртуальной среде и иметь всю необходимую мета-информацию, ради которой, виртуальные машинки обычно и пишутся. Соответственно, чтобы привести синтаксис в соответствие с настоящим компилятором С++, мне иногда приходится проводить забавные эксперименты, о которых нигде не написано и которые обычно никому не приходят в голову.
Я решил собрать в верхнем посте все подобные казусы, ну по типу того, как иногда выходят статьи на Хабре про аналогичные вещи. Поехали:

C++ Source Code:
enum;

С точки зрения языка, конструкция абсолютно бессмысленная, хотя и вполне валидная. В чём секрет? Ну для enum и имя и инициализаторы являются опциональными.

C++ Source Code:
1
typedef class
2
{
3
  int foo;
4
} MyClass;

А тут уже интереснее. Как вы знаете, замута с typdef struct унаследована от Си, а в С++ опциональна. Хотя struct в C++ это тоже класс, просто область доступа у него по дефолту public. Но как видите - различие есть.
Эта конструкция (по крайней мере в MSVC 6.0) компилится, а потом выдаёт ошибку вообще из какого-то произвольного места на этапе линковки.
Попробуйте в других студия, интересно что из этого получится.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено SNMetamorph 28-03-2022 в 09:31:

Почему просто не взять какой-то нибудь AngelScript вместо виртуальной машины?

__________________
Мой сайт
Xash3D Modding Discord


Отправлено Дядя Миша 28-03-2022 в 10:58:

Есть вещи, которые лично меня там не устраивают.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено a1batross 28-03-2022 в 11:18:

typedef class тоже вполне валиден. Не знаю как у тебя что-то на линковке ломается, там уже обычно классов нет.

__________________
Xash3D FWGS форк


Отправлено Дядя Миша 28-03-2022 в 11:42:

Цитата:
a1batross писал:
Не знаю как у тебя что-то на линковке ломается

unresolved external symbol

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 29-03-2022 в 09:14:

Товарищи, нужна ваша небольшая помощь. Если у вас есть под рукой разные компиляторы, потестируйте следующую ситуацию:

C++ Source Code:
1
void TestStackFree( void )
2
{
3
  int	i;
4
 
5
  delete &i;
6
}

Шестёрка, естественно, это жрёт без вопросов даже c Warning Level 4.
Интересно, как обстоят дела на свежих MSVC или GCC или Clang.
Буду признателен.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено SNMetamorph 29-03-2022 в 09:30:

Цитата:
Дядя Миша писал:
Товарищи, нужна ваша небольшая помощь. Если у вас есть под рукой разные компиляторы, потестируйте следующую ситуацию:

C++ Source Code:
1
void TestStackFree( void )
2
{
3
  int	i;
4
 
5
  delete &i;
6
}

Шестёрка, естественно, это жрёт без вопросов даже c Warning Level 4.
Интересно, как обстоят дела на свежих MSVC или GCC или Clang.
Буду признателен.

Clang 13.0.1 - без ошибок, без варнингов
GCC 11.2 - без ошибок, варнинг 'void operator delete(void*, long unsigned int)' called on unallocated object 'i' [-Wfree-nonheap-object]
MSVC 19.31 - без ошибок, без варнингов
ICC 2021.5.0 - без ошибок, без варнингов

Добавлено 29-03-2022 в 13:30:

PVS Studio пишет примерно то же, что и GCC

__________________
Мой сайт
Xash3D Modding Discord


Отправлено Дядя Миша 29-03-2022 в 09:32:

Мда GCC самый умный оказался.
Ну я примерно этого и ожидал.
При освобождении памяти пограммиста поджидает столько граблей, что очуметь можно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено SNMetamorph 29-03-2022 в 09:38:

Цитата:
Дядя Миша писал:
При освобождении памяти пограммиста поджидает столько граблей, что очуметь можно.

Но с другой стороны для этого есть анализаторы кода, которые эту задачу выполняют вполне нормально

__________________
Мой сайт
Xash3D Modding Discord


Отправлено Дядя Миша 18-04-2022 в 12:08:

Никогда об этом не задумывался, но вот такая конструкция

C++ Source Code:
void Test( class *ptr )
{
}

Вполне валидная. Проверьте на GCC и на свежих студиях.
Теоретически это как void но не совсем.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 18-04-2022 в 18:37:

Сегодня выяснил совершенно удивительную вещь. Оказывается в таких языках как Java, C#, PHP, а так же Unigine Script, Angel Script любые методы у объектов нигде не задекларированы и узнать об их наличии можно только из документации. Либо IDE выдаст подсказку выпадающим списком.
Там же по идее нет атомарных типов, ну по крайней мере в Java.
Каждый "простой" тип - это класс с кучей встроенных методов.
И вот нет никакой возможности увидеть хидер этого типа и посмотреть какие методы доступны. Либо через документацию, которая может и устареть, либо через IDE, который тоже непонятно как это показывает.
Ну надеюсь из фреймворка берёт. Если там константные таблички, то это вообще волшебно. Впрочем, для Angel Script положение еще веселее.
Там есть атомарные типы без методов и возможнось зарегистрировать пользовательские типы сравнительно простым образом (за что его многие превозносили - за простоту биндинга). Однако почему-то никому не пришло в голову, что без документации узнать, какие именно есть новые объекты и какие у них методы, попросту невозможно. IDE у AngelScript помоему вообще никакого нет. А документацию, как обычно составляют когда-нибудь потом.
И вы еще спрашиваете, за что я не люблю вот эти языки?
Причём это официально задекларированый механизм. Знающий наизусть все методы в Java может считаться миддлом. Вот так на ровном месте создаются рабочие места и растёт ВВП. Затем выходит новая версия Java и всё можно начинать сначала.

Добавлено 18-04-2022 в 21:37:

Ну и заодно, у вас есть уникальная возможность повлиять на ключевые слова будущего скриптового языка XashNT. Для членов класса (да и не только для них), требуются модификаторы, которые будут разрешать делать ядру с этими переменными определённые действия. Например, передача по сети, сохранение в сейв, итд.

на данный момент я остановился на следующих ключевых словах:

shared - переменная будет передаваться по сети на клиент
persistent - переменная будет сохраняться в сейв
predictable - состояние переменной будет предиктиться на клиенте
field - разрешено записывать в эту переменную настройки из описания энтить уровня, например spawnflags.

Если у вас есть какие-то предложения по иному неймингу, я вас внимательно слушаю. Так же помните, что предложенные вами слова, должны как можно менее точно отражать суть, потому что это общее правило именования всяких вещей, которым суждено стать стандартом. Чем абстрактнее, тем лучше.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 18-04-2022 в 19:22:

Переменные для сохранения? Шта?
Вот посмотри как в юнити сделано:
https://habr.com/ru/post/549018/
https://mirror-networking.gitbook.io/docs/

Можно как то так:
public Network.Shared.Predictable<int> kekcheburek;

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено nemyax 18-04-2022 в 19:23:

То есть как-то так?

C++ Source Code:
1
class target_switch
2
{
3
public:
4
  shared persistent field string target;
5
  target_switch(string init_target) : target(init_target) {}
6
};


Модификаторы мне лично ок.


Отправлено XaeroX 18-04-2022 в 19:30:

Цитата:
nemyax писал:
shared persistent field string target;

public static final void!

__________________

xaerox on Vivino


Отправлено Дядя Миша 18-04-2022 в 19:43:

Цитата:
nemyax писал:
То есть как-то так?

Необязательно. Можно и так
C++ Source Code:
typedef shared predictable persistent vec3 worldpos;
 
worldpos m_origin;

Чтобы каждый раз не прописывать.
Цитата:
FiEctro писал:
public Network.Shared.Predictable<int> kekcheburek;

Жэсть. Такое ощущение, что это не VM, а плюсы измученные шаблонами.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 19-04-2022 в 09:05:

Немного поменял концепцию. Во первых убрал модификатор predictable, поскольку нет нужды это делать выборочно. Всё что попало на клиент нуждается в предиктинге, если включен соответствующий квар.
Т.е. там можно сделать некоторые режимы, типа предиктить всё, предиктить только игроков, а внутри VM это будет только запутывать. Поскольку нам надо предсказывать поведение объектов, а не отдельных переменных.

Вместо этого ввёл модификатор unsigned, который влияет только на сейв-рестор и передачу по сети. Так же важный момент, после объявления переменной через двоеточие объявляется сколько бит использует эта переменная. В VM эта настройка не будет влиять на непосредственно размер переменной (по крайней мере на текущий момент). Вместо этого она будет использоваться как хинт - сколько бит используется в данной переменной для сохранения в сейв и передачи на клиент по сети. Т.е. такой очень удобный и наглядный аналог delta.lst. Безо всяких идиотских таблиц и прочего. Кол-во бит будет работать и на флоатах тоже. Никаких множителей не понадобится, этот способ гораздо точнее и надёжнее. Т.е. по сети можно будет передавать даже восьмибитные флоаты или что-то вроде этого.

Ну а в дальнейшем возможно и реальный размер переменных тоже подгонится под заданный, но я, если честно не вижу в этом особого смысла.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено nemyax 19-04-2022 в 09:35:

Цитата:
Дядя Миша писал:
ввёл модификатор unsigned, который влияет только на сейв-рестор и передачу по сети

При чём тут знаковость?


Отправлено Дядя Миша 19-04-2022 в 09:41:

Цитата:
nemyax писал:
При чём тут знаковость?

При передаче по сети - очень даже при чём! Я больше скажу - в обычной программе народ мешает signed\unsigned и это почти никогда ни к каким проблемам не приводит. Всё дерьмо начинается как раз при передаче по сети.
Ты просто не сталкивался.

Добавлено 19-04-2022 в 12:41:

Собсно, фишка в чём - в знаковой переменной вполне может лежать беззнаковый тип. А это напрямую влияет как будет использован один из битов, заданных для определения размера при передаче по сети.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 19-04-2022 в 14:15:

На мой взгляд, две самые стрёмные операции, которые абсолютно не нужны в скриптовом языке - это взятие адреса и разыменование указателей.
Не берусь предположить, можно ли было без них обойтись в С++, но ведь он вырос из Си, значит следовало обеспечить полную совместимость.
Но поскольку в С++ есть ссылки, потребность во взятии адреса, на мой взгляд отпадает полностью. Обычно адрес берут, чтобы передать в функцию указатель на аргумент, который будет модифицироваться. Ссылка делает тоже самое, только безопасным образом.
Тут идея в чём. Если указатель не был получен легальным образом, значит он использует какие-то объекты, на которые он не нужен. Глобальные или стековые. Здесь ссылка прекрасно годится.

Но конечно я не исключаю, что не учёл чего-то, по мере развития языка будет видно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено AntiPlayer 20-04-2022 в 14:31:

Цитата:
Дядя Миша писал:
На мой взгляд, две самые стрёмные операции, которые абсолютно не нужны в скриптовом языке - это взятие адреса и разыменование указателей.

А я думал, одна из самых важных особенностей скриптовых языков и виртуальных машин в том, чтобы держать кодера подальше от прямого доступа к памяти. Или я неправильно понимаю?

__________________
I tell you to enjoy life


Отправлено Дядя Миша 04-05-2022 в 13:27:

C++ Source Code:
typedef const void	foo;


А ну, вот такую бяку опробуйте

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 07-05-2022 в 08:04:

Делаю свитч-кейсы и встал интересный вопрос. Вот конструкция:

C++ Source Code:
1
void test( int i )
2
{
3
  switch( i )
4
  {
5
  case '1':
6
      break;
7
  case 2:
8
      break;
9
  case "foo":
10
      break;
11
  }
12
}

Шестёрка на последний кейс почему-то ругается case expression not constant. Что за бред? А какая же это строка? Не константная штоле?
Она должна ругаться case expression of type 'const char' is illegal
или что-то вроде этого. Проверьте как ругаются другие компиляторы.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено nemyax 07-05-2022 в 13:39:

Цитата:
Дядя Миша писал:
case expression of type 'const char' is illegal
или что-то вроде этого

Ho "foo" имеет тип const char*.


Отправлено XaeroX 07-05-2022 в 14:43:

Цитата:
Дядя Миша писал:
А какая же это строка? Не константная штоле?

Это не строка, а указатель на некую область памяти, которая будет доступна только при старте программы. В плюсах нет неко ких константных строк, ты при желании можешь её изменить в рантайме.

__________________

xaerox on Vivino


Отправлено Дядя Миша 07-05-2022 в 17:14:

Цитата:
XaeroX писал:
ты при желании можешь её изменить в рантайме

и покоцать образ в памяти?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 16-05-2022 в 09:28:

В делфях оказывается есть указатель на функцию абстрактного класса.
Ну т.е. этот тайпдеф необязательно объявлять внутри класса, можно в глобальном пространстве, а вместо имени класса написать object.
Я ради прикола попробовал объявить нечто подобное в С++

C++ Source Code:
void (class::*foo)( void );

В шестерке сразу получилась INTERNAL_COMPILER_ERROR.
Попробуйте на других компиляторах

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 22-05-2022 в 09:12:

Вот такую конструкцию попробуйте

C++ Source Code:
int foo[2][2] = { 1, 2 };

Я не могу понять, то ли это UB шестёрки, то ли штатная ситуация.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 22-05-2022 в 09:16:

Не знаю, что там в шестёрке, но в нормальном компиляторе это инициализирует первый ряд 1 и 2, а второй ряд - нулями.

__________________

xaerox on Vivino


Отправлено Дядя Миша 22-05-2022 в 11:10:

Дошло. Тут неинтуитивное поведение на самом деле.
Если мы пишем

C++ Source Code:
int foo[8] = { 0 };

У нас массив заполняется нулями. После чего мы вправе(?) ожидать что вот такая конструкция
C++ Source Code:
int foo[8] = { -1 };

Запишет везде -1, однако этого естественно не происходит.
Сама операция присовоения вызывает установку всех элементов массива в 0, кроме тех, для которых значения указаны явно. В первом случае явно указано значение для первого элемента, оно равно нулю, остальные равны нулю по дефолту, из-за чего и формируется ложный стереотип, будто задание еденичного значения забьёт все элементы этим числом. Но в реальности этого конечно не происходит. Аналогичная фигня, кстати и с мемсетом.
Мы задаем ему -1 и ждём, что будет забивать массив наших значений этим числом. Хотя по факту он работает с байтами, т.е. каждый байт 32-битного числа будет забит -1. Что опять-таки явно не то поведение, которое нам бы требовалось. Но в подавляющем большинстве случаев мемсет используется чтобы обнулить память, и это проходит незамеченным. Вполне вероятно, что сам мемсет не стали трогать ради совместимости, сделали еще функцию ZeroMemory, а так же вероятно есть какой-то продвинутый std::memset (но я просто предполагаю), который забивает память вот как раз с учётом типа входного массива.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 22-05-2022 в 18:14:

Цитата:
Дядя Миша писал:
После чего мы вправе(?) ожидать что вот такая конструкция

Это очень странная логика: считать, что если инициализатор не указан, то используется значение предыдущего. Она очень человеческая, но не математическая.
С точки зрения математической логики, кмк, стоит ожидать, что если инициализатор не указан - то используется 0. Ну сам посуди, когда мы видим запись десятичной дроби: 1.2, что логичнее предположить, что она на самом деле "1.222222222222222222..." или "1.2000000000000000..."?

__________________

xaerox on Vivino


Отправлено Дядя Миша 22-05-2022 в 18:36:

Цитата:
XaeroX писал:
Она очень человеческая, но не математическая.

В данном случае я руководствуюсь логикой программиста.
У программиста в программе бывает два количества объектов: еденичный объект и сколько угодно объектов. Таким образом если что-то указано ОДИН РАЗ - значит это надо применить ко всему. Если больше одного, ну неважно сколько - значит имелось в виду что-то еще.
Помоему логично? Потому что в программировании есть волшебные константы 0 и 1. Любые другие числа, это уже хак.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 22-05-2022 в 18:44:

Цитата:
Дядя Миша писал:
я руководствуюсь логикой программиста

Впервые слышу о такой.
Цитата:
Дядя Миша писал:
Таким образом если что-то указано ОДИН РАЗ - значит это надо применить ко всему. Если больше одного, ну неважно сколько - значит имелось в виду что-то еще.

Предположим, у нас есть строка s, заранее выделенная, размером 8 символов.
Тогда, по твоей логике, присвоение:
s = "ab";
даст нам строку "ab", а вот такое присвоение:
s = "a";
даст нам строку "aaaaaaaa", я правильно понял логику программиста?

__________________

xaerox on Vivino


Отправлено Дядя Миша 22-05-2022 в 18:49:

XaeroX всё что я написал выше касается только инициализации массивов, очевидно же. Здесь неинтуитивный момент.
Причём ожидаемое поведение действительно бывает нужно.
Потому что повторюсь, мемсет тоже делает не то, что нужно.
Приходится в цикле присваивать. Т.е. оба способа последовательно фейлят.

Добавлено 22-05-2022 в 21:49:

Цитата:
XaeroX писал:
Предположим, у нас есть строка s, заранее выделенная, размером 8 символов.

Ах да, совсем забыл. В моей VM строки - это не массивы
Это отдельный атомарный тип. Поэтому проблемы нет.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 22-05-2022 в 18:55:

Цитата:
Дядя Миша писал:
всё что я написал выше касается только инициализации массивов, очевидно же. Здесь неинтуитивный момент.

Как раз с житейской точки зрения - очень интуитивный.
Вот допустим, у тебя есть пять коробок, и тебе дали два яблока, положить их по коробкам. Что ты сделаешь? Положишь в две, а три будут пустыми ("инициализированными нулём"). А если у тебя всего одно яблоко - с какого же такого перепугу у тебя в каждой коробке появится по яблоку?
Цитата:
Дядя Миша писал:
Причём ожидаемое поведение действительно бывает нужно.

Для этого в некоторых языках придумали функции типа fill.
Ну или в том же STL, ты можешь написать:
C++ Source Code:
std::vector<int> vec(5, 6);

что создаст тебе вектор из 5 элементов, каждый из которых равен 6.
Это логично, потому что ты сначала задаёшь размер вектора, а потом - чем его инициализировать. Но это неинтуитивно, потому что заменив скобки:
C++ Source Code:
std::vector<int> vec{5,6};

мы получим вектор из двух элементов 5 и 6.
Но это скорее проблема std::initializer_list из С++11, а не логики как таковой.

__________________

xaerox on Vivino


Отправлено Дядя Миша 22-05-2022 в 18:58:

XaeroX неудачный пример. Ты приводишь в пример ресурсы, которые могут дать, а могут и не дать. В данном случае, у нас яблок сколько угодно, но нам лень их раскладывать по коробкам. Мы хотим чтобы все яблоки прыгнули в коробки, по примеру первого.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 22-05-2022 в 18:59:

Цитата:
Дядя Миша писал:
В данном случае, у нас яблок сколько угодно, но нам лень их раскладывать по коробкам. Мы хотим чтобы все яблоки прыгнули в коробки, по примеру первого.

Ок, но тогда и синтаксис должен как-то отличаться, хотя бы скобками, по примеру инициализации вектора. Иначе как мы отличим ситуацию ограниченных ресурсов от неограниченных?

__________________

xaerox on Vivino


Отправлено Дядя Миша 22-05-2022 в 19:04:

Опять же, важный момент замечу.

C++ Source Code:
char foo[32] = { 0 };

Справедливо только для строк, потому что оно делает именно то, что нам надо - обнуляет первый символ. Даже если в остальные согласно какому-то стандарту запишется мусор, это будет уже неважно - главное что первый символ обнулён. Для строки, которая массив это критично важно.
А вот для остальных массивов - не очень, т.к. к ним в нагрузку обычно идёт счётчик использования, который увеличивают уже после того, как очередной элемент был проинициализирован. Т.е. мусор в массиве нас беспокоит меньше всего, за исключением строк, с которыми никто никакой счётчик не таскает, а наоборот - ориентируются по терминатору.
Т.е. твои примеры касательно строк правильные, но для меня неактуалны, т.к. в моем языке строка занимает четырёхбайтный идентификатор, а не массив.

Добавлено 22-05-2022 в 22:03:

Цитата:
XaeroX писал:
Ок, но тогда и синтаксис должен как-то отличаться

Не. Достаточно просто того, что мы указали ОДИН РАЗ. Впрочем, можно вообще убрать нахрен все скобки. Думаю это будет самый оптимальный вариант. Инициализация без скобок вообще забьёт массив одним и тем же числом. Сохраняем совместимость и вводим новую особенность.

Добавлено 22-05-2022 в 22:04:

В крайнем случае можно вывести варнинг nonstandard extension used или что-то вродеэ того.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 22-05-2022 в 19:11:

Цитата:
Дядя Миша писал:
Даже если в остальные согласно какому-то стандарту запишется мусор, это будет уже неважно - главное что первый символ обнулён.

Нет такого стандарта, который поддерживает частичную инициализацию переменной. Нельзя быть немножко беременной и частично инициализированной. Сегодня мы инициализируем только один байт, а завтра что? Инициализируем только пару битов?
Поэтому всегда, если есть конструкция инициализации, переменная гарантированно будет инициализирована целиком. Данными, нулями, вызовом дефолт-конструктора - не суть важно, но мусора там точно не будет.

Добавлено 22-05-2022 в 15:11:

Цитата:
Дядя Миша писал:
Впрочем, можно вообще убрать нахрен все скобки. Думаю это будет самый оптимальный вариант. Инициализация без скобок вообще забьёт массив одним и тем же числом. Сохраняем совместимость и вводим новую особенность.

Этот вариант звучит неплохо, кстати.
Тогда логика будет такая: есть скобки - инициализируем данными из списка инициализации, нет скобок - заполняем одним значением.

__________________

xaerox on Vivino


Отправлено Дядя Миша 22-05-2022 в 19:13:

Цитата:
XaeroX писал:
Тогда логика будет такая: есть скобки - инициализируем данными из списка инициализации, нет скобок - заполняем одним значением.

Да, особенно если учесть, что студия выдаёт ошибку при попытке прямого присвоения к массиву, это не вызовет разночтений.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 28-05-2022 в 12:13:

Расскажу вам как появился знаменитый баг компилятора MSVC 6.0, связанный с выпадением счётчика цикла за пределы видимости самого цикла.
Очень просто. Дело в том, что любая область внутри фигурных скобок считается как область подвидимости функции. Причём компилятор не различает к чему относятся эти скобки, для него это просто новая секция.
И такое поведение в принципе корректно для любых конструкций. Больше нигде никаких переменных не объявляется, ни в do ни во while, ни в switch ни в if. А чистый Си не дозволял объявлять в секции инициализации for новые переменные. Ну вот так этот баг только для одного for и приключился.
Невнимательность
Там надо было зайти в подобласть видимости уже после ключевого слова for.
Вот и вся хитрость.

Добавлено 28-05-2022 в 15:13:

Очередная чумовая проверка компиляторов на вшивость

C++ Source Code:
1
while( 0 )
2
{
3
  int	i;
4
}

В чём тут смысл:
1. условие константное
2. условие никогда не будет выполнено
Следовательно код в секции - мёртвый и его можно вообще скипнуть, не пытаясь распарсить. А как это проверить? Ну вот суём и смотрим - будет ли ругань на unreferenced local variable в разных режимах компиляции.
Если код был просто пропущен, то ессно ругани не будет.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 06-06-2022 в 14:24:

Очередная чумовая проверка компиляторов от дяди Мишы.
Вставьте куда-нибудь вне любой функции неименованый блок скобок

C++ Source Code:
{
}

И посмотрите как будет ругаться компилятор. Вы возможно не задумывались, но это запрещённая конструкция по сути. Неименованный блок скобок возможен только внутри тела функции, как subscope.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 08-06-2022 в 15:46:

Очевидное-невероятное. Шестёрка всё-таки даёт создать конструкцию вида

C++ Source Code:
typedef class *class_t;

Но при попытке что-то присвоить такому указателю выдаётся ошибка:
C++ Source Code:
'=' : cannot convert from 'class CScriptCompiler *const ' to 'class $S60 *'

Что это за класс $60?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 08-06-2022 в 15:47:

Цитата:
Дядя Миша писал:
Что это за класс $60?

Безымянный класс, что тебя смущает?
Это совершенно легальная конструкция в плюсах. Но указатель бесполезен, да.

__________________

xaerox on Vivino


Отправлено Дядя Миша 08-06-2022 в 15:55:

ЗЫ. от константности никак не зависит, всё равно не даёт.
Чувствую себя Скаржем, у которого унреал не запустился на 8086.

Добавлено 08-06-2022 в 18:48:

Цитата:
XaeroX писал:
Это совершенно легальная конструкция в плюсах.

Так у меня она не только легальная, но и юзабельная. Я её использую как указатель на абстрактный класс.

Добавлено 08-06-2022 в 18:55:

Цитата:
XaeroX писал:
Безымянный класс, что тебя смущает?

Да гдеж он безымянный? Доллар по 60 называется.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 08-06-2022 в 15:56:

Цитата:
Дядя Миша писал:
Да гдеж он безымянный? Доллар по 60 называется.

Ты навсякий случай много таких классов не создавай. А то по двести будет!

__________________

xaerox on Vivino


Отправлено Crystallize 08-06-2022 в 16:16:

Цитата:
Дядя Миша писал:
Вы возможно не задумывались, но это запрещённая конструкция по сути.

Недавно узнал что переменные в Си можно объявлять не только в начале функции но и в любом месте, как в плюсах, если поставить вот такие скобки. В коде не попадалось такое.


Отправлено XaeroX 08-06-2022 в 16:42:

Crystallize
Но они будут видны только внутри этих скобок.

__________________

xaerox on Vivino


Отправлено Дядя Миша 08-06-2022 в 19:02:

Цитата:
Crystallize писал:
если поставить вот такие скобки

У меня есть именованный subscope, но я так и не придумал какой от него прок.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено KiQ 08-06-2022 в 20:33:

Цитата:
Дядя Миша писал:
Очередная чумовая проверка компиляторов от дяди Мишы.
Вставьте куда-нибудь вне любой функции неименованый блок скобок
C++ Source Code:
{
}

И посмотрите как будет ругаться компилятор. Вы возможно не задумывались, но это запрещённая конструкция по сути. Неименованный блок скобок возможен только внутри тела функции, как subscope.


В яве таким образом обозначаются блоки инициализации. Статический вариант вызывается при инициализации класса в принципе, а нестатический - при создании каждого экземпляра. Удобно, на самом деле, если хочется запихнуть какую-то рутину вне конструктора

__________________
-Brain is dead-


Отправлено Crystallize 09-06-2022 в 02:43:

Цитата:
Дядя Миша писал:
У меня есть именованный subscope, но я так и не придумал какой от него прок.

Дополнительная разметка кода для чайников? Коммент для конкретного фрагмента кода?


Отправлено Дядя Миша 09-06-2022 в 06:14:

Цитата:
Crystallize писал:
Дополнительная разметка кода для чайников?

Ну, по нему можно делать поиск

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено PRoSToTeM@ 15-06-2022 в 20:58:

Цитата:
Crystallize писал:
Недавно узнал что переменные в Си можно объявлять не только в начале функции но и в любом месте, как в плюсах, если поставить вот такие скобки. В коде не попадалось такое.

Да и без этих скобок можно в любом месте как в плюсах начиная с C99, но студия до недавних пор плохо умела в C99.

Добавлено 15-06-2022 в 23:58:

Цитата:
Дядя Миша писал:
Дошло. Тут неинтуитивное поведение на самом деле.
Если мы пишем
C++ Source Code:
int foo[8] = { 0 };

У нас массив заполняется нулями. После чего мы вправе(?) ожидать что вот такая конструкция
C++ Source Code:
int foo[8] = { -1 };

Запишет везде -1, однако этого естественно не происходит.
Сама операция присовоения вызывает установку всех элементов массива в 0, кроме тех, для которых значения указаны явно. В первом случае явно указано значение для первого элемента, оно равно нулю, остальные равны нулю по дефолту, из-за чего и формируется ложный стереотип, будто задание еденичного значения забьёт все элементы этим числом. Но в реальности этого конечно не происходит.

В языке Pawn есть синтаксис с многоточием для ожидаемой инициализации всего массива одним значением:
C++ Source Code:
new arr[8] = {-1, ...} // -1, -1, -1, ..., -1

Правда там через это же многоточие можно и арифметические прогрессии устроить:
C++ Source Code:
new arr[8] = {1, 2, ...} // 1, 2, 3, 4, 5, ..., 8


Отправлено Дядя Миша 16-06-2022 в 08:47:

PRoSToTeM@ я уже сделал заполнение одним значением через

C++ Source Code:
int aray[8] = -1;

с выдачей предупреждения о nonstandard extension used.

Добавлено 16-06-2022 в 11:47:

Очередной прикол, лишний раз показывающий, что модификаторы типов контекст вообще не учитывают, по крайней мере в шестёрке.

C++ Source Code:
1
mutable enum foo
2
{
3
  TEST = 0,
4
};

Попробуйте на остальных компиляторах. MSVC 6.0 это прекрасно собирает.

Впрочем собирается даже вот такое
C++ Source Code:
1
virtual enum foo
2
{
3
  TEST = 0,
4
};

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено PRoSToTeM@ 16-06-2022 в 11:41:

Цитата:
Дядя Миша писал:
PRoSToTeM@ я уже сделал заполнение одним значением через
C++ Source Code:
int aray[8] = -1;

с выдачей предупреждения о nonstandard extension used.

Тоже неплохой вариант.

Цитата:
Дядя Миша писал:

C++ Source Code:
1
mutable enum foo
2
{
3
  TEST = 0,
4
};

На gcc и clang ошибка, MSVC выдаёт варнинг.

Цитата:
Дядя Миша писал:

C++ Source Code:
1
virtual enum foo
2
{
3
  TEST = 0,
4
};

Аналогично, на двух ошибка, в MSVC варнинг.

Ты можешь и сам проверять на этом godbolt.org, плюс ещё можно на en.cppreference.com посматривать описание языка с примерами.


Отправлено Дядя Миша 17-06-2022 в 09:50:

Вот еще любопытная шляпа:

C++ Source Code:
void (Test)( void )
{
}

Скобки просто выбрасываются, т.е. это обычная функция.
А вот так
C++ Source Code:
void (*Test)( void )
{
}

разумеется уже ошибка. Указатель на функцию не ждёт объявления тела.

Добавлено 17-06-2022 в 12:50:

Возможно это какое-то историческое наследие - объявление имени функции в скобках.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено PRoSToTeM@ 17-06-2022 в 19:15:

Дядя Миша, это чтобы аналогично названный функциональный макрос не раскрывался (например, isdigit).
https://stackoverflow.com/questions...ction-name-mean


Отправлено Дядя Миша 17-06-2022 в 19:47:

Да уж

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено PRoSToTeM@ 20-06-2022 в 01:19:

Цитата:
Дядя Миша писал:
Необязательно. Можно и так
C++ Source Code:
typedef shared predictable persistent vec3 worldpos;

Блин, опять typedef с перепутанными аргументами. В плюсах же есть нормальный typedef:
C++ Source Code:
using worldpos = shared predictable persistent vec3;

Правда ключевое слово не самое подходящее. Я бы рассмотрел такие варианты:
C++ Source Code:
typedef worldpos = shared predictable persistent vec3;

C++ Source Code:
type worldpos = shared predictable persistent vec3;

C++ Source Code:
typealias worldpos = shared predictable persistent vec3;

C++ Source Code:
typename worldpos = shared predictable persistent vec3;


Отправлено XaeroX 20-06-2022 в 01:51:

Лучше alias, да. Потому что typedef это довольно неудачное ключевое слово, оно не создает новый тип.

__________________

xaerox on Vivino


Отправлено Дядя Миша 20-06-2022 в 06:17:

Цитата:
XaeroX писал:
оно не создает новый тип.

А чтож оно по твоему делает? Удаляет старый тип?
Using у меня ассоциируется с неймспейсами и тоже не создаёт ничего нового.

Добавлено 20-06-2022 в 09:17:

А typename это вообще для шаблонофф.
Я не намерен коверкать синтаксис, пока язык не будет завершен.
Пусть он для начала получит возможности на уровней той же MSVC 6.0.
По большей части, во всяком случае. А потом посмотрим.
Кое-что я с удовольствием возьму из свежих редакций.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 20-06-2022 в 07:34:

Цитата:
Дядя Миша писал:
А чтож оно по твоему делает?

Всё что угодно, только не создаёт новый тип.
Ради смеху можешь попробовать создать перегрузку функции с типом, созданным через typedef (например, typedef int BOOL), и с оригинальным int. Ты увидишь, что для компилятора и то и другое - самый обычный int.
Для создания strong types в плюсах нужно использовать классы с операторами, больше никак.

__________________

xaerox on Vivino


Отправлено Дядя Миша 20-06-2022 в 07:41:

Цитата:
XaeroX писал:
Всё что угодно, только не создаёт новый тип.

Ну это как бы большой вопрос - а что вообще можно считать новым типом.
Атомарные типы, мы очевидно не можем конструировать с нуля, а значит всё что мы создадим будет алиасами.

Цитата:
XaeroX писал:
Ради смеху можешь попробовать создать перегрузку функции с типом, созданным через typedef (например, typedef int BOOL), и с оригинальным int. Ты увидишь, что для компилятора и то и другое - самый обычный int.

Неправда, так себя только шестёрка ведёт, а новые студии уже нет.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 20-06-2022 в 08:12:

Цитата:
Дядя Миша писал:
а новые студии уже нет.

Ну-ну.

__________________

xaerox on Vivino


Отправлено PRoSToTeM@ 20-06-2022 в 13:11:

Цитата:
Дядя Миша писал:

Неправда, так себя только шестёрка ведёт, а новые студии уже нет.

Нет, это везде провоцирует redefinition.


Отправлено Дядя Миша 08-07-2022 в 15:50:

Ну хорошо, вот такой вам тест:

C++ Source Code:
1
class Foo
2
{
3
  int	test;
4
 
5
  union
6
  {
7
    float	bar;
8
    void moo( void ) {}
9
  };
10
};

В чём тут смысл - nameless юнионы поидее не должны позволять иметь в своём составе функции. Ну или как минимум - конструкторы и деструкторы.
Причём если с конструкторами как бы понятно - ведь имя конструктора базируется на имени класса, а если имени нет, то и конструктор откуда возьмётся? Это в делфях конструктор имеет особую метку и всегда называется Create, но в делфи конструкторы запрещены даже в структурах, не то что в юнионах. Что-то я отвлёкся. Суть в том, что шестёрка это компилит, но при попытке обратится к moo говорит, что такого мембера - нет. Интересно как на других компиляторах.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено TheEVolk 08-07-2022 в 16:13:

Цитата:
Дядя Миша писал:
Жэсть. Такое ощущение, что это не VM, а плюсы измученные шаблонами.

В typescript есть декораторы, можно сделать так:

@Predictable()
@Shared()
@Network()
const myValue = 123;

Или:
@Flags(FLAG_PREDICTABLE + FLAG_SHARED)
const myValue = 123;

Добавлено 09-07-2022 в 00:13:

Жесть, я забыл страницу перелистнуть и ответил на сообщение многомесячной давности 0_0

__________________
exit();


Отправлено Дядя Миша 08-07-2022 в 16:17:

Цитата:
TheEVolk писал:
Жесть, я забыл страницу перелистнуть и ответил на сообщение многомесячной давности 0_0

Мне пришлось всю тему перечитать, чтобы вспомнить о чём собственно шла речь

Цитата:
TheEVolk писал:
В typescript есть декораторы, можно сделать так:

Угу или создать новый язык Kotlin. Тоже неплохой вариант.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 14-07-2022 в 10:42:

Вот какую любопытную вещь обнаружил:

C++ Source Code:
1
class Base
2
{
3
  virtual void Foo( void ) = 0;
4
};
5
 
6
void Base :: Foo( void )
7
{
8
}

То есть pure virtual function получает тело и шестёрка на это никак не ругается.

Добавлено 14-07-2022 в 13:42:

С удивлением обнаружил, что параметры вызова функции нельзя перечислять, как объявленные типы. Ну т.е. вот так писать нельзя:
C++ Source Code:
void Arc( int X1, Y1, X2, Y2, X3, Y3, X4, Y4 )
{
}

Никогда раньше над этим не задумывался.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 05-08-2022 в 10:09:

Вот еще какую штуку планирую ввести - предупреждение при копировании объекта сквозь аргумент функции. За все годы практики я совершенно не припомню случаев, когда такое бывало нужно. К тому же подобное копирование вообще может быть опасно, если в объекте наличествуют умные указатели и RC. Или манипуляции с глобальными переменными в конструкторе. Запрещать такое поведение конечно не стоит - мало ли.
Но выдавать предупреждение четвертого уровня, что может быть имелась в виду передача по ссылке\указателю, думаю нужно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено KiQ 14-09-2022 в 19:33:

Цитата:
Дядя Миша писал:
С удивлением обнаружил, что параметры вызова функции нельзя перечислять, как объявленные типы

Строгая типизация же, ну. Собственно наверное в VM это омжно обойти, всегда парся аргументы функции на наличие двух литералов, из первого выводить тип и назначать его всем последующим аргументам, пока не попадётся следующее такое выражение. Но система это крайне нестабильная, имхо, и в байт-коде всё равно будет необходимо это заменить на явное объявление. То есть, типичный синтаксический сахар выходит

Добавлено 14-09-2022 в 22:33:

Ну или как вариант все аргументы одного типа заключать в дополнительные скобки, навроде:
void Arc( int (X1, Y1, X2, Y2, X3, Y3, X4, Y4), float scale, int (r,g,b) ) {}

Хотя слишком совпадает с сигнатурой функции, принимающей аргументы в виде функции. Можно, например использовать многоточие после типа:
void Arc( int... X1, Y1, X2, Y2, X3, Y3, X4, Y4, float scale, int... r,g,b ) {}

__________________
-Brain is dead-


Отправлено Дядя Миша 15-09-2022 в 09:45:

Цитата:
KiQ писал:
Строгая типизация же, ну

Нет, она тут непричём. В Delphi разные типы отделяются точкой с запятой, а в Си - только запятая. Т.е. невозможно было бы различить где идёт перечисление имён переменных одного типа, а где начался новый тип.
К тому же Си допускает объявление только типа переменной, без его имени, а в Delphi так писать нельзя.

Добавлено 15-09-2022 в 12:45:

Дошли руки до тернарной операции. Ну это просто if с обязательным else.
Но встал вопрос, чем она оперирует? Выражениями или статементами?
Всю жизнь полагал, что только выражениями, ну сейчас вот проверил.

C++ Source Code:
void *a = NULL
bool result = a ? { true } : { false };

Такое действительно не компилится. А интересно, может в новых студиях разрешили, хотя вриатле.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 17-09-2022 в 11:46:

Как вы знаете, конструкторы\деструкторы есть даже у тривиальных типов.
Я правда хз, как это реализовано на уровне компилятора, потому что POD не считается классом, как это могло бы быть например сделано в том же Шарпе.
То есть это такой фейк, который не всегда срабатывает. Скажем в шестёрке вызов конструктора\деструктора надо непременно делать, взяв указатель на объект. Пример

C++ Source Code:
1
int	a;
2
int	*b = &a;
3
 
4
b->int();
5
b->~int();

Причём мякотка в том, что вызов конструктора - компилится, а на вызов деструктора шестёрка долго ругается, но прикол в том, что проблемы с вызовом шестёркой деструкторов были признаны официально и скорее всего в новых студиях это даже корректно скомпилируется.
Аналогичным образом осуществляется и доступ через точку
C++ Source Code:
1
int	a;
2
 
3
a.int();
4
a.~int();

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

C++ Source Code:
class Foo : public int
{
};

Шестёрка сразу ругается про неожиданный тип, но может свежие студии не будут?

Добавлено 17-09-2022 в 14:23:

Становится всё интереснее. Пример кода:

C++ Source Code:
1
int		a;
2
 
3
a.int( 0 );
4
 
5
Msg( "a: %d\n", a );

получаю предупреждение
Цитата:

warning C4700: local variable 'a' used without having been initialized

Причём в конструкторе можно от балды передать сколько угодно параметров, это ни на что не повлияет и не приведёт к ошибке. И передавать можно тоже всё что угодно, главное чтобы такая переменная реальная существовала Т.е. blabla написать не получится.
Судя по всему компилятор парсит эти параметры и тут же их выбрасывает, да и самого вызова конструктора как такового - не происходит.

Добавлено 17-09-2022 в 14:46:

Ну чтож, последний тест, который даёт полное право утверждать, что вызов конструктора у тривиальных типов - это хак и фейк
C++ Source Code:
int		a;
 
a->int();

Даже вот такая конструкция прекрасно компилируется.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 17-09-2022 в 13:12:

Ух сложно. Дядя Миша скажи, а насколько твой синтаксис будет совместим с шарповым?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 17-09-2022 в 13:27:

С шарповым ровно настолько, насколько сам шарп совместим с С++.
Мой язык максимально близок именно к синтаксису С++, хотя есть и отличия.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 18-09-2022 в 08:39:

Дошли руки до ссылок. Насколько я знаю, очень многие путают ссылки с указателями и думают, что это практически одно и тоже, но не всё так просто. Поясню чем они отличаются. Я сам не заглядываю ни в какие исходники компиляторов С++, ну просто потому что там чёрт ногу сломит, дольше разбираться, поэтому не могу 100% утверждать, что оно там устроено точно также, но общий смысл всё равно сохраняется - просто исходя из логики и семантики самого языка. Так вот смысл в том, что указатель - это пользовательская конструкция. Мы туда вручную записываем какой-то адрес, например тот, который вернул malloc и взятие адреса на какую-то переменную. В то же время, компилятор сам активно берёт адреса на те или иные объекты, которые не становятс от этого типом указателя.
Например доступ в структуру так или иначе осуществляется по указателю.
Берём адрес на начало объекта, прибавляем смещение до желаемой переменной. Адресс есть, а указателя нет. В чистом Си подобные конструкции надёжно скрыты внутри компилятора и пользовать не имеет к ним доступа. Ну а в С++ дали возможность работать с подобными адресами.
Вот такой адрес и есть ссылка. В чём разница? Когда мы передаём аргумент на указатель в функцию, то на стек помещается копия адреса этого указателя. То есть мы можем изменять содержимое по указателю, но вот сам указатель изменять уже не можем. Точнее можем, но эти изменения не повлияют на сам аргумент, переданный в функцию. Для выхода из положения можно воспользоваться указателем на указатель, но вы без меня знаете, что это самая стрёмная и неудобная конструкция в Си С++, потому что понять где и что именно мы меняем уже почти невозможно. Две звёдочки ещё туда-сюда, а вот на четырёх-пяти, у меня уже полностью выключается мозг. Вы спросите, куда нужно столько звёзд? Ну например массив двухмерных матриц.
Но есть и еще важный момент. У класса, переданного по ссылке могут быть пользовательские операторы, например []. А теперь угадайте с трёх раз
к чему будет применён оператор [], если взять указатель на класс? Ну правильно, к самому указателю
Со ссылкой такого не происходит, понятно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 25-09-2022 в 10:47:

Сделал шаблоны, ну пока только на классы. Может показаться, что шаблон на функцию ввести легче, однако это не так. Потому что перегрузка функций, блин! А шаблонные функции учитываются дедуктором тоже, что его значительно осложняет. Как вы знаете если у вас есть шаблонная функция, то вовсе необязательно при её вызове указывать foo<int>, можно просто написать foo, она должна корректно обнаружиться (даже при условии, что инстанцирование вообще не было произведено), затем, будет выполнено сравнение по кол-ву аргументов, чтобы решить, надо ли в данном случае вообще выполнять инстанцирование, или пока еще рано, затем собственно, сконструировать такую функцию и запустить её в общее пространство. С классом гораздо проще - если встретился незнакомый тип, за которым идёт скобка < то это полюбому шаблон. Возможно, необъявленный, но шаблон. Как вы знаете шаблон класса объявить неявным образом нельзя.
Хотя хрен знает, может быть в каких-то новых студиях и можно, я уже запутался в этих стандартах. Так же хочу отметить, что исходник класса для шаблона хранится и парсится целиком, без какого-либо разбора на отдельные функции. Это приводит к забавному эффекту - если внутри шаблонного класса были объявлены всяческие конструкторы и копи-конструкторы, то компилятор немедленно начинает их требовать у класса-аргумента typename. Настоящая студия, как вы помните так себя не ведёт - она не конструирует шаблонные функции класса до последнего момента или делает их во время надписи Generating code... Соответственно, если функция не была вызвана, то она даже распарсена не будет, таким образом ошибки в шаблонах могут годами лежат незамеченными, главное не вызывать явным образом функцию, содержащую ошибку. Но вот теперь я даже прямо не знаю - это баг или фича? Оставить или сделать как в настоящей студии, хотя это довольно непростая задачка и я её в любом случае напотом оставлю.
Так же более-лименее разобрался с конструкторами тривиальных типов.
Ну я выше про них писал. Оказывается что компилятор различает ГДЕ был вызван это конструктор - в теле шаблона или просто пограммист баловался. Так вот если в теле шаблона, то обычный конструктор для тривиальных типов не делает вообще ничего, а копи-конструктор инициирует либо присвоение, либо вызов копи-конструктора у самого класса-аргумента, либо вызов memcpy. У меня лично нет вызова memcpy, хотя по сравнению С++ в моём языке копировать объекты через Memcpy даже с виртуальными функциями абсолютно безопастно. Ну потому что в C++ виртуальная таблица наглухо встроена в сам объект и её адреса - локальные. А в у меня это просто хэндл на индексированную структуру RTTI, которую компилятор строит в любом случае, даже если никаких виртуальных методов у класса нет. Строит для доступа в бакэнде к любой переменной, для сериализации, ну и вообщще для манипуляции с верхнего уровня, как говорится, ведь в этом и смысл виртуальной машины - для возможности такого доступа. Поэтому у меня копирование объектов через memcpy абсолютно безопасно, но компилятор пока что сам не провоцирует подобные вызовы вместо copy constructora.
Я пока не определился как будет лучше. Учтите, что это один из самых стрёмных моментов в плюсах, когда неявно сгенерированный вызов memcpy в MSVC потом порождает порчу кучи и вообще цепочку трудно-объяснимых багов, которые лечатся созданием корректного копи-конструктора, но естественно никакого сообщения об ошибке, которое могло бы натолкнуть программиста на мысль об этом не выдаётся.

Добавлено 25-09-2022 в 13:47:

Вот какая мысль мне пришла. Перед тем как сделать вызов memcpy для копирования одного объекта в другой, компилятор может пройтись по всем членам класса, а если эти члены - сами объекты, то и внутри по их членам класса, и при обнаружении в классе хоть одного указателя - выдать предупреждение о небезопасности такого копирования. Но вы должны понимать, что если кто-то скастует указатель в int, то это обнаружить уже нипочём не удастся. Впрочем, если кто-то занимается подобными вещами, он наверное знает что делает?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено a1batross 27-09-2022 в 09:20:

Дядя Миша к слову, да, помнится по неопытности затирал классы memset, пока не выстрелил в колено пустым vtable.

Если сразу ориентироваться на людей далеких от программирования, то такая диагностика -- это только хорошо. Любят нынче строгие компиляторы, но не осуждаю.

__________________
Xash3D FWGS форк


Отправлено Дядя Миша 27-09-2022 в 10:52:

Цитата:
a1batross писал:
к слову, да, помнится по неопытности затирал классы memset

У меня это тоже можно, т.к. хэндл vtable находится в самом начале памяти объекта. Но нулевой объект - это заглушка, так что приложение не упадёт, а просто взорвётся сообщениями про pure virtual method и продолжит свою работу. Впрочем уронить "до винды" тоже можно. Хотя я конечно и принял все возможные меры для противодействия этому. Но раз есть указатели, взятие указателей и дереференс, возможности выстрелить себе в ногу кратно возрастают.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 10-10-2022 в 10:41:

Начал вот тут разбираться с анализатором недостижимого кода и обратил внимание, что студии в принципе плевать на такие условия как if( 0 )
Она их не считает за мёртвый код. То есть вот такое вот:

C++ Source Code:
1
void TestDeadCode( void )
2
{
3
  return;
4
 
5
  Msg( "dead-code\n" );
6
}

Однозначно детектируется, а условия игнорятся. Ну мало ли.
Проверьте в новых студиях, только не забудьте включить максимальный уровень предупреждений компилятора, а то не выдаст вообще ничего.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 29-11-2022 в 15:45:

Ну что же, пришла пора завезти в язык перегрузку операторов.
Это гораздо проще, нежели внедрение, скажем, ссылок, но есть и свои тонкости. Во первых складывается впечатление, что модель перегрузки операторов завязанная на обычные функции не совсем идеально соответствует поставленной задаче, но альтернативы в С++ всё равно нету.

Вот скажем, чтобы определить постфиксный оператор ++ или --, надо добавлять дополнительный аргумент оператору, который... не будет использоваться. А как иначе отличить префиксный оператор от постфиксного?

Скрытый текст:
Этот текст скрытый. Вы должны оставить хотя бы одно сообщение в теме, чтобы его увидеть.

Ксерокс, ЕМНИП вообще был уверен, что перегрузка постфиксного оператора невозможна. Потом опять же, в теории каждый оператор должен обходиться двумя операндами. Вернее говоря, каждое выражение должно быть разобрано таким образом, чтобы получилось максимум два операнда.
И да, это практически во всех случаях соблюдается. Кроме одного случая - оператора []. Ведь мы же не знаем скольки мерный массив там может быть в теории? Значит нам нужно как минимум распарить вперёд всю цепочку [][][] чтобы подсчитать хотя бы кол-во операндов. Да и сам принцип, когда каждый аргумент соответствует каждому индексу доступа в массиве несколько неинтуитивен. Прикол в том, чтоб это обычно юзают максимум для одномерных массивов, поэтому считается, что проблемы нет.
Так же неинтуитивны все эти копи-конструкторы, который по сути является неявным оператором присвоения, но вам надо как минимум точно отделить ситуацию когда вызывается именно копи-конструктор, а когд оператор присвоения. В противном случае у вас при попытке копирования классов с виртуальными методами будет гарантированный крэш. Прикол еще и в том, что С++ никак не предупреждает об отсутствии пользовательского копи-конструктора и оператора присвоения. Камрад Ксерокс мне так и сказал, а зачем? Это мол штатная ситуация, здесь и нет никакой ошибки. Это работа для статистических анализаторов. Да, разделение труда - всё-таки великая вещь. Так вот товарищи, по факту т.н. "поэлементное копирование класса" на самом деле скорее всего через memcpy происходит. Либо там не вызывается дефолтный конструктор при подобном копировании. Корочи говоря, будет вылет и вы даже не поймете почему. Я в своём языке стараюсь все ситуации которые меня бесили в оригинальном С++ вешать на новые варнинги, чтобы пограммист был в курсе событий. Хотя кто его знает, может в новых студиях эти варнинги уже имеются, а в шестёрке их ещё не было?
Так же предстоит сделать кастомные операторы приведения типов, это вообще отдельный механизм, но сперва надо правильно расставить приоритеты встроенным операторам.

Добавлено 29-11-2022 в 18:45:

ЗЫ. совсем забыл. Я планирую сделать возможность превращать свойства в операторы. Но не так по идиотски как это сделано в делфи, а с возможностью множественного выбора. Они будут одновременно и операторами копирования и приведения типов и индексированного доступа.
И свойства в этом плане гораздо нагляднее всех этих копи-конструкторов.
Хотя традиционные подходы С++ тоже останутся, разумеется.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 29-11-2022 в 15:51:

Цитата:
Дядя Миша писал:
Ксерокс, ЕМНИП вообще был уверен, что перегрузка постфиксного оператора невозможна.

Глупости какие. Там дополнительный неиспользуемый инт в сигнатуру добавляется и всё.
Цитата:
Дядя Миша писал:
Так вот товарищи, по факту т.н. "поэлементное копирование класса" на самом деле скорее всего через memcpy происходит.

Нет, там делается поэлементное копирование мемберов. Это и есть копи конструктор по умолчанию. То есть мембер std::string скопируется вполне корректно, т.к. у него есть копи-конструктор, который и будет вызван.

__________________

xaerox on Vivino


Отправлено Дядя Миша 29-11-2022 в 15:53:

ЗЗЫ. Если вдруг кто не знал, у операторов && и || при перегрузке исчезает ленивость, что на мой взгляд делает их перегрузку полностью бессмысленной.

Добавлено 29-11-2022 в 18:53:

Цитата:
XaeroX писал:
Нет, там делается поэлементное копирование мемберов

Тогда почему vtable херится?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 29-11-2022 в 15:58:

Цитата:
Дядя Миша писал:
у операторов && и || при перегрузке исчезает ленивость

Очевидно, исчезает, потому что теперь это функции со своими правилами sequencing.
Цитата:
Дядя Миша писал:
делает их перегрузку полностью бессмысленной

Нет, не делает: http://cpptruths.blogspot.com/2014/...-and-using.html

Добавлено 29-11-2022 в 10:58:

Цитата:
Дядя Миша писал:
Тогда почему vtable херится?

А она херится?

__________________

xaerox on Vivino


Отправлено Дядя Миша 29-11-2022 в 16:01:

Тернарка в шаблоне для возвращения ленивости?

Добавлено 29-11-2022 в 18:59:

Цитата:
XaeroX писал:
А она херится?

естественно

Добавлено 29-11-2022 в 19:01:

Возьми класс с виртуальными методами, сделай шаблонный массив и покопируй из него элементы при условии что никаких явных копиконструкторов и операторов присвоения у него нет. vtable будет испорчена.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 29-11-2022 в 16:09:

Цитата:
Дядя Миша писал:
естественно

Да кто тебе сказал такую глупость.

Добавлено 29-11-2022 в 11:09:

Цитата:
Дядя Миша писал:
Возьми класс с виртуальными методами, сделай шаблонный массив и покопируй из него элементы при условии что никаких явных копиконструкторов и операторов присвоения у него нет. vtable будет испорчена.

Я думаю, здесь проблема не в наличии копи-конструктора, а в том, что компилятор не может вывести правильный тип. Когда ты копируешь из класса в класс, у тебя один и тот же тип и идентичная втабля. Её и копировать-то не надо. Главное - не затереть.

__________________

xaerox on Vivino


Отправлено Дядя Миша 29-11-2022 в 16:14:

Цитата:
XaeroX писал:
у тебя один и тот же тип и идентичная втабля

Как она может быть идентичной, если в С++ она таскается вместе с объектом?
ну то есть да, по содержимому она идентична, но адреса-то все разные там.

Добавлено 29-11-2022 в 19:13:

Цитата:
XaeroX писал:
Её и копировать-то не надо.

Так понятно, что не надо, но этож не я с ней что-то делаю, а компилятор.

Добавлено 29-11-2022 в 19:14:

Цитата:
XaeroX писал:
Я думаю, здесь проблема не в наличии копи-конструктора, а в том, что компилятор не может вывести правильный тип.

Поэкспериментируй сам. Может быть компиляторы со времён шестёрки поумнели и больше так не делают.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 29-11-2022 в 16:31:

Цитата:
Дядя Миша писал:
ну то есть да, по содержимому она идентична, но адреса-то все разные там.

Там разве не оффсеты хранятся? Этот момент я запамятовал.
Цитата:
Дядя Миша писал:
Поэкспериментируй сам

Ну я сделал простой эксперимент с классом с данными, без копи конструктора и с виртуальными функциями, всё копируется правильно. Но я брал GCC какой-то свежей версии.

__________________

xaerox on Vivino


Отправлено Дядя Миша 29-11-2022 в 18:27:

Цитата:
XaeroX писал:
Там разве не оффсеты хранятся?

Не, там поидее уникальные адреса. Хотя для GCC может как-то иначе это реализуется? Реализация vtable кроме общих моментов разве предмет стандартизации? Помоему даже её размер никак не регламентирован.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 02-12-2022 в 08:53:

Так товарищи, самый важный вопрос!

Попробуйте скомпилировать этот код:

C++ Source Code:
int		i = 0, j;
 
j = ++i++;

Шестёрка выдает error C2105: '++' needs l-value по вполне понятным причинам. Интересно как ведут себя другие компиляторы.

Между прочим, знаменитая пугалка
C++ Source Code:
j = ++i++ + ++i++;

Аналогично не компилируется, и у меня в языке оно аналогично.
Вот и думаю, вкорячить туда UB чтоб собиралось или действительно пусть выдаёт ошибку?

Добавлено 02-12-2022 в 11:49:

Я поясню, почему происходит именно так.
Первым вызывается префиксный инкремент, однако для него ещё нет переменной, поэтому рекурсивно вызывается парсер очередного выражения, который разбирает постфиксный инкремент.
На уровне опкодов, это выглядит примерно так:

C++ Source Code:
c = a; a += 1;


Тонкость в том, что c, это lvalue перед =. Оно приходит в префиксное выражение, но не приходит в постфиксное. Его туда без проблем можно пропустить, но нужно ли?

Добавлено 02-12-2022 в 11:52:

Проще говоря UB заключается в нагромождении дополнительных условий внутри операторов, ну типа если lvalue == void, взять i как lvalue.
Вот так оно и появляется, например. Но есть ли в этом смысл?

Добавлено 02-12-2022 в 11:53:

Вот я пропустил lvalue j внутрь суффиксного инкремента. Для выражения

C++ Source Code:
j = ++i++ + ++i++;

у меня получился результат
i = 2, j = 3
не думаю что это правильно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 02-12-2022 в 11:19:

А где это можно использовать?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 02-12-2022 в 12:19:

Нигде, естественно. Это одна из тех идиотских задачек, которые любят задавать на собеседованиях.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 02-12-2022 в 12:20:

Дядя Миша
Вот тут подробно написано про sequence points и order of evaluation:
https://en.cppreference.com/w/cpp/language/eval_order

__________________

xaerox on Vivino


Отправлено Дядя Миша 02-12-2022 в 12:48:

XaeroX ты невнимательно читал мой пост. Я спрашивал вот это вот

C++ Source Code:
j ++i++;

Вообще в принципе хоть где-то скомпилируется или нет?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 02-12-2022 в 13:42:

Цитата:
Дядя Миша писал:
Нигде, естественно. Это одна из тех идиотских задачек, которые любят задавать на собеседованиях.



Тогда почему просто ошибку не вывести?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 02-12-2022 в 14:44:

Так я пытаюсь понять что должно компилироваться, а что нет.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 02-12-2022 в 15:05:

Дядя Миша
Если это UB - то никто никому ничего не должен.

__________________

xaerox on Vivino


Отправлено Дядя Миша 03-12-2022 в 13:07:

Ну чтож, насколько я могу судить, источником UB служит только и исключительно префиксный инкремент\декремент. Всё остальное детерминировано.

Добавлено 03-12-2022 в 16:07:

Итак, товарищи, я опять со своими глупостями. Поскольку компиляторы не жрут выражения вида ++i++ мы упростим себе задачку и оставим только четыре комбинации из префиксных и постфиксных выражений.
Выглядит это вот так:

code:
int main() { { int i = 0; int j = ++i + ++i; printf( "%i = ++i + ++i; %i = i;\n", j, i ); } { int i = 0; int j = i++ + i++; printf( "%i = i++ + i++; %i = i;\n", j, i ); } { int i = 0; int j = ++i + i++; printf( "%i = ++i + i++; %i = i;\n", j, i ); } { int i = 0; int j = i++ + ++i; printf( "%i = i++ + ++i; %i = i;\n", j, i ); } return 0; }

С точки зрения юзера (то есть меня), порядок выполнения во всех случаях должен быть следующим:
C++ Source Code:
inc( a );
inc( b );
c = a + b;

Однако инкременты напрямую влияют на процесс парсинга выражений, из-за чего там всё может меняться местами в случайном порядке. Это поведение происходит из-за того, что компиляторы С\С++ в сущности ведут себя подобно ассмеблеру - что читаю, тут же генерирую код.
Ну поумнее конечно чем транслятор ассемблера, но вот такие фокусы там никак не обрабатываются. Ваша задачка засунуть эти примеры UB в разные студии и скинуть сюда результаты выполнения.

Подам пример:
HeadShot v 0.43
C++ Source Code:
1
4 = ++i + ++i; 2 = i;
2
4 = i++ + i++; 2 = i;
3
4 = ++i + i++; 2 = i;
4
4 = i++ + ++i; 2 = i;


MSVC 6.0
C++ Source Code:
1
4 = ++i + ++i; 2 = i;
2
0 = i++ + i++; 2 = i;
3
2 = ++i + i++; 2 = i;
4
2 = i++ + ++i; 2 = i;

Здесь как видите UB в полный рост. Интересно будет сравнить результаты с более свежими студиями.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дикс 03-12-2022 в 13:15:

Студия 19

4 = ++i + ++i; 2 = i;
0 = i++ + i++; 2 = i;
2 = ++i + i++; 2 = i;
2 = i++ + ++i; 2 = i;

с форума копипастится вместе с номерами строк
Залил исходный код на https://pastebin.com/vFkruZpB

__________________
igroprom.d3.ru


Отправлено Дядя Миша 03-12-2022 в 13:16:

Если между шестёркой и 19-й студией отличий нет, думаю во всей линейке микрософтовских компиляторов их и не будет. Но всякие там GCC любопытно было бы взглянуть, да.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дикс 03-12-2022 в 13:20:

4 = ++i + ++i; 2 = i;
1 = i++ + i++; 2 = i;
3 = ++i + i++; 2 = i;
2 = i++ + ++i; 2 = i;

g++ --version
g++ (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.

__________________
igroprom.d3.ru


Отправлено Дядя Миша 03-12-2022 в 13:41:

Полная версия экспериментов:

C++ Source Code:
1
4 = ++i + ++i; 2 = i;
2
4 = i++ + i++; 2 = i;
3
4 = ++i + i++; 2 = i;
4
4 = i++ + ++i; 2 = i;
5
2 = ++i++; 2 = i;
6
0 = ++i--; 0 = i;
7
0 = --i++; 0 = i;
8
-2 = --i--; -2 = i;
9
8 = ++i++ + ++i++; 4 = i;
10
14 = ++i++ + ++i++ + ++i++; 6 = i;

Последние пять примеров студией не скомпилятся.

Добавлено 03-12-2022 в 16:41:

Кстати вот это вот ++i-- на баш.орге когда-то назвали "оператор подёргивания", если кто-то ещё помнит.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 04-12-2022 в 12:52:

Вот ещё какая шляпа выяснилась. Я над этим не задумывался просто потому, что оно мне было не нужно. Дело в том, что new для массива возможен только с дефолтным конструктором. Нельзя написать что-то типа

C++ Source Code:
new foo( 1 )[100];

Ну то есть может оно и можно, но шестёрка не даёт этого сделать.
Причём сам массив работает как для классов, так и для POD-типов, но кастомный конструктор тут вызвать нельзя. Впрочем у меня наверное вообще не будет этой возможности, т.к. она вступает в серъезные противоречия с концепцией всей виртуальной машины. Ну или если быть точным - это же придётся городить какую-то отдельную структуру, которая во первых будет разом высвобождать всё, а во вторых её надо где-то хранить и оберегать от попыток высвободить память через free, например.

Добавлено 04-12-2022 в 15:52:

ЗЫ. Эта штука вообще походу какой-то костыль, потому что, например нельзя написать вот так
C++ Source Code:
new foo[100][100];

Т.е. многомерный массив таким образом тоже не сделать. Впрочем его обычно используют для выделения массива POD-типов или АТД-типов.
Чего-то такого без виртуальных деструкторов. Во избежание.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 05-12-2022 в 13:28:

Дядя Миша
Скажи, а как в твоей виртуальной машине будет обрабатываться порядок событий?
https://habr.com/ru/post/147315/
https://docs.unity3d.com/ru/530/uploads/Main/monobehaviour_flowchart.svg

Можно будет обращаться к скрипту как компоненту энтитии? Например на объекте висит скрипт вызывающий класс Ригидбоди. Каким образом к нему обратиться у тебя?

Как можно будет задать объектам и физике слои, чтобы одни могли видеть друг друга, а другие нет?

Куда завернуты материалы с шейдерами? Как с ними общаться через скрипт?

Возможно будет сделать выполнение скрипта прямо в редакторе?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 05-12-2022 в 14:38:

Я в этой схеме вообще не вижу клиент-серверной архитектуры, поэтому такого порядка событий у меня и не будет. Да и вообще тут странно приоритеты расставленны.

Цитата:
FiEctro писал:
Можно будет обращаться к скрипту как компоненту энтитии?

Не совсем. Предполагается на что на скриптовом языке будет полностью написана вся игровая часть кода, как в Quake. Это самый удобный вариант.
Если же объекты существуют внутри движка, а взаимодтействие с ними идёт через различные скрипты, обязательно возникнут ситуации, которые не решаются и которые пообещают решить в новой версии. Я заведомо не хочу создавать такую ситуацию.

Цитата:
FiEctro писал:
Например на объекте висит скрипт вызывающий класс Ригидбоди

Вот есть Half-Life SDK написанный на С++. А теперь представь что вместо С++ - мой скриптовой язык. Который специально точился под все эти игровые особенности и заморочки. То есть будут такие же библиотеки как для халфы с очень-очень похожим на С++ кодом. Но с кучей возможностей, нереализуемых на С++ безкостыльными методами.

Цитата:
FiEctro писал:
Как можно будет задать объектам и физике слои, чтобы одни могли видеть друг друга, а другие нет?

Но в физике нет понятия "видеть". Должно быть ты имел в виду столкновения?

Цитата:
FiEctro писал:
Куда завернуты материалы с шейдерами? Как с ними общаться через скрипт?

Через скрипт я думаю никак, да и навряд ли это понадобится. Вот из материала прочитать свойства объекта - это да, такая возможность будет. На мой взгляд это гораздо более оптимально.

Цитата:
FiEctro писал:
Возможно будет сделать выполнение скрипта прямо в редакторе?

Редактор сможет симулировать игровой мир, да.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 05-12-2022 в 15:10:

Цитата:
Дядя Миша писал:
Я в этой схеме вообще не вижу клиент-серверной архитектуры, поэтому такого порядка событий у меня и не будет. Да и вообще тут странно приоритеты расставленны.


Не очень понятно, а каким образом синхронизироваться с тактами физдвижка к примеру? Ну допустим если у нас такты физики считаются допустим фиксировано в 25фпс, а камера аттачится к такому объекту при нефиксированом фпс, это приведёт к подергиваниям. Придется городить костыли с высчитыванием дельты? А если я хочу вызвать скрипт когда уже кадр отрисован?

Цитата:
Дядя Миша писал:
Не совсем. Предполагается на что на скриптовом языке будет полностью написана вся игровая часть кода, как в Quake. Это самый удобный вариант.
Если же объекты существуют внутри движка, а взаимодтействие с ними идёт через различные скрипты, обязательно возникнут ситуации, которые не решаются и которые пообещают решить в новой версии. Я заведомо не хочу создавать такую ситуацию.


Я про другое, вот допустим у тебя есть объект, он наследует класс ригидбоди, у которого например есть булева - ис кинематик. Так вот как мне её переключать? А если я например создаю инстансами эти объекты и мне надо у какого то из них переключить эту булеву?

Цитата:
Дядя Миша писал:
Вот есть Half-Life SDK написанный на С++. А теперь представь что вместо С++ - мой скриптовой язык. Который специально точился под все эти игровые особенности и заморочки. То есть будут такие же библиотеки как для халфы с очень-очень похожим на С++ кодом. Но с кучей возможностей, нереализуемых на С++ безкостыльными методами.


Т.е. будет некий init.cpp из которого вызываем все наши функции, правильно?

Цитата:
Дядя Миша писал:
Но в физике нет понятия "видеть". Должно быть ты имел в виду столкновения?


Самый простой пример - трасса из ориджина объекта, сталкивается с его собственным колайдером. Как это решить?

Цитата:
Дядя Миша писал:
Через скрипт я думаю никак, да и навряд ли это понадобится. Вот из материала прочитать свойства объекта - это да, такая возможность будет. На мой взгляд это гораздо более оптимально.


Ну вот у меня есть простой шейдер, который по локальной нормали объекта рисует тень на глазах, и всё бы ничего пока ты не начнешь вращать башкой. Для этого я передаю vector3 поворота кости головы прямиком в шейдер. Это даже умеет убогий game maker самых древних версий, а ты говоришь не нужны. Или предполагается создавать 3 отдельных флоата в самом материале?

Цитата:
Дядя Миша писал:
Редактор сможет симулировать игровой мир, да.


Супер, и гизмо можно рисовать?

И самое интересное, будет ли какой то быстрый способ использовать движковый таймер и синхронизироваться с ним?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 05-12-2022 в 16:42:

Цитата:
FiEctro писал:
Ну допустим если у нас такты физики считаются допустим фиксировано в 25фпс, а камера аттачится к такому объекту при нефиксированом фпс, это приведёт к подергиваниям

Ну ты в спирите небось аттачил разные камеры к разным объектам, ничего же не дёргалось?

Цитата:
FiEctro писал:
А если я хочу вызвать скрипт когда уже кадр отрисован?

Если ты вызываешь скрипт, когда кадр уже отрисован - ты его вызываешь на новом кадре

Цитата:
FiEctro писал:
Я про другое, вот допустим у тебя есть объект, он наследует класс ригидбоди, у которого например есть булева - ис кинематик. Так вот как мне её переключать?

А, да так же как в кваке. MOVETYPE, SOLID. Физдвижок не в скриптах, он неявно довлеет над ситуацией, а ты просто задаешь ему что симулировать и как. Классы - не наследуют никаких физических типов. Но каждому объекту можно задать любой тип симуляции, например.

Цитата:
FiEctro писал:
Т.е. будет некий init.cpp из которого вызываем все наши функции, правильно?

Ну там не совсем. Интерфейсы будут, как туда, так и оттуда.

Цитата:
FiEctro писал:
Самый простой пример - трасса из ориджина объекта, сталкивается с его собственным колайдером. Как это решить?

Ну а как решали в Кваке? Задвали хозяина. Трасса не коллидит со своим хозяином. А групповые коллизии через маску задаются, да это и в халфе было. И в физиксе оно так же.

Цитата:
FiEctro писал:
Для этого я передаю vector3 поворота кости головы прямиком в шейдер

Ты опять не понял. Не надо ничего передавать из игрового кода прямо в шейдер. Материал сам возьмёт любой параметр из объекта, по его имени тогда, когда посчитает нужным. Объясняю. Допустим ты в классе завёл какую-то переменную и туда сохранил чего тебе надо. Дальше ты в описании материала заводишь новый юниформ vec3 и пишешь слинковать его с entity->myCoolVariable; И всё, материал сам профетчит эту переменную из текущего объекта при условии что текущий объект будет иметь модель, у которой будет хотя бы один такой материал.
Тебе не надо будет внутри самого объекта заниматься какими-то бесконечными SetUniform, достаточно просто обновлять переменную.

Цитата:
FiEctro писал:
Супер, и гизмо можно рисовать?

А что такое Гизмо?

Цитата:
FiEctro писал:
И самое интересное, будет ли какой то быстрый способ использовать движковый таймер и синхронизироваться с ним?

А что такое движковый таймер?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 05-12-2022 в 17:02:

Цитата:
Дядя Миша писал:

А что такое Гизмо?

Это босс казино из первого Fallout.
https://fallout.fandom.com/wiki/Gizmo

Добавлено 05-12-2022 в 12:02:

Там у него очень любопытная анимация смерти, жестокая и кровавая. Видимо, от этого и пошло выражение "рисовать Гизмо".

__________________

xaerox on Vivino


Отправлено FiEctro 05-12-2022 в 18:00:

Цитата:
Дядя Миша писал:
А что такое Гизмо?


Гизмо это всякие фигуры и линии в редакторе. Например визуализация триггеров, трассы или нормалей.


Цитата:
Дядя Миша писал:
Ну ты в спирите небось аттачил разные камеры к разным объектам, ничего же не дёргалось?


Хотелось полного контроля над такими вещами.

Цитата:
Дядя Миша писал:
А, да так же как в кваке. MOVETYPE, SOLID. Физдвижок не в скриптах, он неявно довлеет над ситуацией, а ты просто задаешь ему что симулировать и как. Классы - не наследуют никаких физических типов. Но каждому объекту можно задать любой тип симуляции, например.


Я не помню уже как в кваке. Но если можно без особых костылей, уже хорошо.

Цитата:
Дядя Миша писал:
Ты опять не понял. Не надо ничего передавать из игрового кода прямо в шейдер. Материал сам возьмёт любой параметр из объекта, по его имени тогда, когда посчитает нужным. Объясняю. Допустим ты в классе завёл какую-то переменную и туда сохранил чего тебе надо. Дальше ты в описании материала заводишь новый юниформ vec3 и пишешь слинковать его с entity->myCoolVariable; И всё, материал сам профетчит эту переменную из текущего объекта при условии что текущий объект будет иметь модель, у которой будет хотя бы один такой материал.
Тебе не надо будет внутри самого объекта заниматься какими-то бесконечными SetUniform, достаточно просто обновлять переменную.


Ну я так и думал, материал просто изменяет переменную в шейдере, а мы изменяем её в материале через скрипт.

Цитата:
Дядя Миша писал:
А что такое движковый таймер?


Ну вот ты вызвал функцию, и внутри неё тебе что то нужно вызвать допустим ровно через 10 секунд, независимо от фпс. Как в таком случае будет выглядеть код, без костылей вроде всяких циклов?

Цитата:
XaeroX писал:
Там у него очень любопытная анимация смерти, жестокая и кровавая. Видимо, от этого и пошло выражение "рисовать Гизмо".


Гизмо переводится буквально как ШТУКА.


А поддержка листов будет? https://metanit.com/sharp/tutorial/4.5.php
Да и вообще планируются какие нить фичи из шарпа? Было бы прикольно если ВМ хоть частично была с ним совместима.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 05-12-2022 в 19:00:

Цитата:
XaeroX писал:
Это босс казино из первого Fallout.

А, крепкий хозяйственник.

Цитата:
FiEctro писал:
Например визуализация триггеров, трассы или нормалей.

Дебуг-отрисовка корочи. Отладочная визуализация.

Цитата:
FiEctro писал:

Хотелось полного контроля над такими вещами.

Чтобы дёргалось? О каком контроле речь?

Цитата:
FiEctro писал:
материал просто изменяет переменную в шейдере, а мы изменяем её в материале через скрипт.

Материал позволяет подключать новые переменные к шейдеру, какие угодно. У тебя же есть доступ к бета-тестированию, почитай документацию, там всё это подробно расписано.

Цитата:
FiEctro писал:
и внутри неё тебе что то нужно вызвать допустим ровно через 10 секунд, независимо от фпс

Ну а как тчинки в кваке работали? SetNextThink( 10.0f ); и вызов будет ровно через 10 секунд, независимо от фпс.

На самом деле я вообще не понимаю тех проблем, которые сами себе придумали авторы современных движков.

Добавлено 05-12-2022 в 21:57:

Цитата:
FiEctro писал:
А поддержка листов будет?

Мой язык позволяет не просто реализовать динамические массивы, но еще и шаблонные массивы, как в настоящем С++.
Вообщем представь себе язык с возможностями С++. Ну конечно он помедленее чем С++ работает, но по возможностям его даже превосходит в некоторых аспектах. По крайней мере в тех, которые нужны в играх и именно поэтому я так и заморочился созданием собственного языка, а не взял чужой.

Добавлено 05-12-2022 в 22:00:

Цитата:
FiEctro писал:
Да и вообще планируются какие нить фичи из шарпа?

В шарпе абсолютно всё встроено внутрь стандартных объектов. Такой подход есть абсолютное зло, потому что во первых без редактора\документации понять что именно там есть невозможно.
А во вторых, рано или поздно каких-то возможностей не хватит и тогда встречайте новую версию шарпа, которая несовместима с преведущей.
В моём языке есть всего три базовых типа, int, float и string. А всё остальное пользователь создаёт самостоятельно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 05-12-2022 в 20:02:

Цитата:
Дядя Миша писал:
В моём языке есть всего три базовых типа, int, float и string. А всё остальное пользователь создаёт самостоятельно.


Ну вот в этом и проблема, вместо того чтобы писать код игры, приходится писать какие то дурацкие структуры (в юнити например вопрос указателей и структур опущен, хоть они там и есть в полной мере как и в си++) и у каждого разраба они написаны по своему. Кто во что горазд короче, отсутсвует какая то стандартизация. Может я конечно С++ очень плохо знаю, но всё же всякие заготовленные объекты сильно облегчают задачу новичкам, да и читабельность кода. Хотелось бы услышать твоего совета по этой ситуации. Возможно в базовом скрипте будут какие то заготовки?

Добавлено 05-12-2022 в 23:02:

Цитата:
Дядя Миша писал:
Чтобы дёргалось? О каком контроле речь?


Порядок вызова и возможность синхронизации как с физикой, так и с обычным фпс, а так же возможность выполнить код как можно позже.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 05-12-2022 в 20:15:

Цитата:
FiEctro писал:
Ну вот в этом и проблема, вместо того чтобы писать код игры, приходится писать какие то дурацкие структуры

Зачем? Я сам всё напишу и ротатаблю тоже. Будет несколько типовых заготовок-сценариев для различных игр.

Цитата:
FiEctro писал:
Порядок вызова и возможность синхронизации как с физикой, так и с обычным фпс

Обычно такой выбор не имеет смысла. Если это игровые объекты, они сихронизируются с серверным временем, если локальные - то с клиентским.

Цитата:
FiEctro писал:
возможность выполнить код как можно позже.

Еще в первой кваке были trigger_relay с возможностью задания любого времени действия. На одном из уровней, к примеру триггер срабатывал через несколько минут после старта.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 05-12-2022 в 20:46:

Цитата:
Дядя Миша писал:
Обычно такой выбор не имеет смысла. Если это игровые объекты, они сихронизируются с серверным временем, если локальные - то с клиентским.


А с рендером и физикой?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 05-12-2022 в 21:04:

рендер - клиентское время, физика - серверное.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 06-12-2022 в 08:21:

Выяснилось жуткое. Сам я над этим никогда не задумывался, а тут вдруг внезапно понял. Вот казалось бы, если мы создаём объект дочернего класса через new, а результат кастуем к родительскому классу, что в этом такого особенного?
Пример

C++ Source Code:
1
class CBaseEntity
2
{
3
public:
4
  CBaseEntity() { Msg( "CBaseEntity ctor called\n" ); }
5
  ~CBaseEntity() { Msg( "CBaseEntity dtor called\n" ); }
6
  string_t	m_classname;
7
  vec3	m_origin;
8
};
9
 
10
class CInfoPoint : CBaseEntity
11
{
12
public:
13
  CInfoPoint() { Msg( "CInfoPoint ctor called\n" ); }
14
  virtual ~CInfoPoint() { Msg( "CInfoPoint dtor called\n" ); }
15
  string_t	m_target;
16
};

Этот класс мы пытаемся создать вот так
C++ Source Code:
1
CBaseEntity	*e;
2
 
3
e = new CInfoPoint;
4
delete e;

И шо бы вы думали? Получаем ошибку
Цитата:

error C2243: 'type cast' : conversion from 'class CInfoPoint *' to 'class CBaseEntity *' exists, but is inaccessible

Честно говоря я такой ошибки не получал примерно никогда вообще
Но ладно, мало ли. Может это на выражение new действует такое строгое условие, а если это сделать чуть ниже, то норм? Ок, видоизменяем код
C++ Source Code:
1
CBaseEntity	*e2;
2
CInfoPoint	*e;
3
 
4
e = new CInfoPoint;
5
e2 = e;
6
delete e;

И снова получаем ту же самую ошибку!
Цитата:

error C2243: 'type cast' : conversion from 'class CInfoPoint *' to 'class CBaseEntity *' exists, but is inaccessible

Странно. dynamic_cast в данном случае бесполезен, ведь мы идём вверх по иерархии, а не вниз. О чём компилятор честно предупреждает
Цитата:

dynamic_cast used to convert to inaccessible or ambiguous base; run-time test will fail ('class CInfoPoint *' to 'class CBaseEntity *')

Тогда нам нужен static_cast? И снова получаем ошибку
Цитата:

error C2243: 'static_cast' : conversion from 'class CInfoPoint *' to 'class CBaseEntity *' exists, but is inaccessible

Ну зараза, я тебя всё-таки победю! Через Си-шный каст
C++ Source Code:
1
CBaseEntity	*e2;
2
CInfoPoint	*e;
3
 
4
e = new CInfoPoint;
5
e2 = (CBaseEntity *)e;
6
delete e2;

И вот ошибка превращается в предупреждение
Цитата:

warning C4243: type cast conversion from 'class CInfoPoint *' to 'class CBaseEntity *' exists, but is inaccessible

На самом 4243 это и есть предупреждение, которое почему-то форсируется до ошибки.
Запускаем! Ну и получаем вот это

Добавлено 06-12-2022 в 11:17:

Иными словами - хотя у нас есть виртуальный деструктор, при принудительном кастовании указателя вверх там внутри ломается вообще всё. И деструктор CInfoPoint не вызывается, да еще и память повреждается.
Очуметь можно. Просто в Шоте это вполне себе законная конструкция.

Добавлено 06-12-2022 в 11:21:

Скорее всего подобное поведение происходит из-за возможности множественного наследования в С++, там каждый наследный класс имеет свою базу и свой уникальный указатель. Но когда множественного наследования нет, то и этой проблемы нет тоже. Кстати в Делфи аналогично.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 06-12-2022 в 14:43:

Цитата:
Дядя Миша писал:
И шо бы вы думали? Получаем ошибку

Приватное наследование, оно такое.

__________________

xaerox on Vivino


Отправлено Дядя Миша 06-12-2022 в 16:29:

XaeroX а оно по дефолту приватное разве?

Добавлено 06-12-2022 в 19:28:

Да, публичное наследование работает.

Добавлено 06-12-2022 в 19:29:

Но при условии, что в базовом объекте тоже объявлена vtable.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 06-12-2022 в 17:00:

Цитата:
Дядя Миша писал:
а оно по дефолту приватное разве?

Для классов по дефолту приватное, для структур по дефолту публичное.

__________________

xaerox on Vivino


Отправлено FiEctro 06-12-2022 в 17:21:

Цитата:
Дядя Миша писал:
Я сам всё напишу и ротатаблю тоже.


Насколько будет интуитивным управление трансформом, скейлом и ротейтом объектов? А так же преобразвания углой Эйлера в кватернионы и обратно. Ну и преобразования из локальных пространств в глобальные и наоборот.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 06-12-2022 в 20:22:

Цитата:
FiEctro писал:
Насколько будет интуитивным управление трансформом, скейлом и ротейтом объектов?

Это всё очень субьективно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 07-12-2022 в 06:01:

Цитата:
Дядя Миша писал:
Это всё очень субьективно.


А что может быть субъективного в этих простых операциях? Просто не превращать их в простыню кода для пользователя, а то ещё и матрицы считать заставишь

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 07-12-2022 в 06:52:

Цитата:
FiEctro писал:
А что может быть субъективного в этих простых операциях?

Как бы ни было просто, всегда найдётся тот, кто скажет "нипанятнааа".

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 07-12-2022 в 07:18:

Дядя Миша
Так, а что может быть непонятного в одной функции? Нет, ну если там помимо этого нужно ещё городить огород, то да.

Кстати вопрос немного не по теме, но всё же я хочу спросить тебя, по поводу парентов в халфе и спирите, почему с ними были такие трудности? Я насколько помню адекватно работающие паренты ты реализовал уже в ксашмоде только когда уже перенес его на ксашдвижок. Халфа не умеет работать с локальными пространствами? Интересен этот исторический момент.

И какова архитектура дочерних объектов будет в новом движке? Можно фрактально теже ротатабли друг в друга вложить?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 07-12-2022 в 08:07:

Цитата:
FiEctro писал:
почему с ними были такие трудности?

Исторически преобразования пространства это тежолые матричные вычисления, компьютеры тогда не тянули, вот и не делали.
Я помню когда-то форк квейка на плейстейшон вита доделывал, решил ему замутить корректную трассу об ротатабли, ессно матричную. Так фпс после моей доработки упал вдвое

Цитата:
FiEctro писал:
Я насколько помню адекватно работающие паренты ты реализовал уже в ксашмоде только когда уже перенес его на ксашдвижок.

Так физика была в движке зашита, а без переделки физики получались сплошные костыли. Можно было бы заморочиться и сделать адекватные паренты в халфе, просто из спортивного интереса, Ксерокс кажется делал в Хеткрап Френзи.

Цитата:
FiEctro писал:
И какова архитектура дочерних объектов будет в новом движке? Можно фрактально теже ротатабли друг в друга вложить?

Вложенность есть иллюзия на самом-то деле. Под вложенностью понимается некоторый уровень наследования. Ну например, что дочерние объекты будут:
1. видны вместе с родительским
2. будут наследовать перемещения родительского объекта
3. будут удалены одновременно с родительским объектом
Какие еще условия можно тут унаследовать?
Наследование можно сделать через пространство имён так же как в С++, например. Это для доступа к таким объектам. Этот вопрос будет решаться во время создания редактора.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 07-12-2022 в 08:55:

Цитата:
Дядя Миша писал:
Исторически преобразования пространства это тежолые матричные вычисления, компьютеры тогда не тянули, вот и не делали.


Ну с костями же это всё работает, и для скелеталки это даже в халфе работало. Чем она отличаются от всех остальных объектов?

Цитата:
Дядя Миша писал:
Какие еще условия можно тут унаследовать?


Позиция, угол, скейл.

Цитата:
Дядя Миша писал:
Наследование можно сделать через пространство имён так же как в С++, например. Это для доступа к таким объектам. Этот вопрос будет решаться во время создания редактора.


В Юнити есть ещё такой прикол как префабы, это по сути отдельная сцена с объектами, которую ты можешь вставлять внутрь другой сцены. В том числе распаковывать префаб в обычные объекты сцены с учетом всех трансформаций что ты применял для префаба.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено (_-=ZhekA=-_) 07-12-2022 в 10:39:

Цитата:
FiEctro писал:
это по сути отдельная сцена с объектами, которую ты можешь вставлять внутрь другой сцены.

В UE4 можно создать уровень в котором можно создавать еще уровни, типа слои, например, у нас есть основной левел и в нем еще несколько отдельных левелов с освещением, коллизией, звуками, и так далее

__________________
Kiss my ass if you don't like my Ford!
------------------------------------------
Game Area51 Update 1
First Person Shooter Released Jul 24, 2017
The game is a 3d shooter with the elements of the quest.

http://button.moddb.com/download/medium/125531.png


Отправлено FiEctro 07-12-2022 в 11:01:

Цитата:
(_-=ZhekA=-_) писал:
В UE4 можно создать уровень в котором можно создавать еще уровни, типа слои, например, у нас есть основной левел и в нем еще несколько отдельных левелов с освещением, коллизией, звуками, и так далее


Да у Юнити и УЕ примерно одинаковая логика, а в УЕ5 буквально с Юнити интерфейс слизали. Я когда зашел, даже офигел, сначала думал что не разберусь, а потом почти с набегу даже поимпортировал ресурсы, собрал небольшую сцену. Сразу видно хотят переманить к себе Юнитистов, и надо сказать у них хорошо получается.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено (_-=ZhekA=-_) 07-12-2022 в 11:23:

Цитата:
FiEctro писал:
а в УЕ5 буквально с Юнити интерфейс слизали.

Почти сразу с ue4 пересел на ue5 и до сих пор матерюсь на новый дизайн редактора... Ппй какой не удобных после четверки... Но уже почти привык )))

Цитата:
FiEctro писал:
Да у Юнити и УЕ примерно одинаковая логика

Хз, я юнити даже не запускал )

__________________
Kiss my ass if you don't like my Ford!
------------------------------------------
Game Area51 Update 1
First Person Shooter Released Jul 24, 2017
The game is a 3d shooter with the elements of the quest.

http://button.moddb.com/download/medium/125531.png


Отправлено Дядя Миша 07-12-2022 в 11:54:

Цитата:
FiEctro писал:
Ну с костями же это всё работает, и для скелеталки это даже в халфе работало

Ну ты сравнил стек костей, который в кэш помещался для еденичного объекта и хаотично разбросанные по всей памяти.

Цитата:
FiEctro писал:
В Юнити есть ещё такой прикол как префабы, это по сути отдельная сцена с объектами, которую ты можешь вставлять внутрь другой сцены

Я эту фишку придумал ещё в нулевые. Думаю это что-то такое самоочевидное.

Цитата:
FiEctro писал:
Позиция, угол, скейл.

А зачем скейл наследовать? Приведи пример.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 07-12-2022 в 13:40:

Цитата:
Дядя Миша писал:
А зачем скейл наследовать? Приведи пример.


А зачем скейл наследуют кости? Ну например чтобы одновременно скейлить дочерние объекты с разным скейлом. Чем сидеть высчитывать отдельно для каждого. Можно ещё такие желеподобные штуки делать физические (софтбоди), и тоже их скейлить так удобно, поскольку они состоят из нескольких ригидбоди с джоинтами.

В Юнити кстати скелеталка это обычные игровые объекты с иерархией, т.е. к любой кости можно свободно прикрепить скрипт, объект, или вообще вытащить эту кость на сцену из иерархии. Ну или даже дополнить скелет новыми косточками прямо в самом редакторе Юнити, например чтобы добавить ИК контролеры.

Цитата:
Дядя Миша писал:
Ну ты сравнил стек костей, который в кэш помещался для еденичного объекта и хаотично разбросанные по всей памяти.


А родитель разве не единичный объект? Как он по памяти хаотично разбросан может быть? Я думал все объекты хранятся в каком то едином массиве чтобы по ним легко можно было поиск делать. Особенно это актуально для сохранений и ченжлевелов.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 07-12-2022 в 14:16:

Цитата:
FiEctro писал:
Как он по памяти хаотично разбросан может быть?

Каждый объект в той же халфе - это отдельный маллок, т.к. их размеры отличаются. Вот в кваке, там да, был единый гигантский массив.
Но я не только об этом. Кости в одной функции считались и массив там умещался в кэше, причём считался только для объектов, которые видны игроку.
А физика с парентами считалсь бы всегда и везде для всего мира.

Цитата:
FiEctro писал:
Ну например чтобы одновременно скейлить дочерние объекты с разным скейлом.

Очевидно речь идёт не об абсолютном масштабе, а об относительном.
Т.е. исходный скейл у дочерних объектов может быть каким угодно, но если к родительскому будет применено его изменение, то и к дочерним тоже. Это да.

Цитата:
FiEctro писал:
В Юнити кстати скелеталка это обычные игровые объекты с иерархией

Это еще с третьего дуума пошло Кармак был первым это придумал.

Цитата:
FiEctro писал:
А родитель разве не единичный объект?

Всё относительно. Родитель может быть и чьим-то дочерним объектом одновременно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 10-12-2022 в 07:42:

Я вот как-то не задумывался, а теперь, так сказать столкнулся. Если мы объявляем статичный динамический массив внутри класса, очевидно, что его размер будет объявлен позднее, т.к. мы не можем проинициализировать этот массив прямо внутри класса. Однако функция, которая будет обращаться к этому массиву может находиться внутри тела класса. До тех пор пока она просто обращается к массиву никаких проблем не возникает. Но если мы попытаемся применить sizeof к такому вот оператору, то...
Проиллюстрирую на примере

C++ Source Code:
1
#define ARRAYSIZE( p )		(sizeof( p ) / sizeof( p[0] ))
2
struct test_t
3
{
4
  const char	*name;
5
  int		value;
6
};
7
 
8
class CArrayTest
9
{
10
public:
11
  static test_t	m_entries[];
12
public:
13
  void Test( void )
14
  {
15
    Msg( "arraysize: %d\n", ARRAYSIZE( m_entries ));
16
  }
17
};
18
 
19
test_t CArrayTest :: m_entries[] =
20
{
21
  { "Test1", 1 },
22
  { "Test2", 2 },
23
  { "Test3", 3 },
24
};

Дело в том, как вы знаете, что sizeof срабатывает по месту вставки, немедленно. А у нас массив-то ещё непроинициализирован!!!! А функция, где его размер должен быть взят находится ВЫШЕ, чем инициализация массива, хотя бы потому, что С++ не позволяет инициализировать массивы, принадлежащие классу внутри его тела. Даже если это статичные массивы. Ну вот нельзя и всё тут. Таким образом, когда мы берём размер m_entries, он у нас равен []. И получаем ошибку
Цитата:
error C2070: illegal sizeof operand

Решение заключается в том, чтобы вынести функцию вычисления размера массива после, собственно, его инициализации. То есть вот так:
C++ Source Code:
1
#define ARRAYSIZE( p )		(sizeof( p ) / sizeof( p[0] ))
2
class CArrayTest
3
{
4
public:
5
  static test_t	m_entries[];
6
public:
7
  void Test( void );
8
};
9
 
10
test_t CArrayTest :: m_entries[] =
11
{
12
  { "Test1", 1 },
13
  { "Test2", 2 },
14
  { "Test3", 3 },
15
};
16
 
17
void CArrayTest :: Test( void )
18
{
19
  Msg( "arraysize: %d\n", ARRAYSIZE( m_entries ));
20
}

Этот вариант компилируется без проблем. Но мне стало любопытно. А может быть некоторые компиляторы настолько продвинутые, что используют подобие deferred sizeof? Проверьте пожалуйста первый вариант на различных компиляторах, как они себя поведут.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 31-01-2023 в 15:31:

Пришла мне в голову вот какая идея. Всем известно что занулять класс с виртуальными методами при помощи memset нельзя - будет сплошной вылет, да и только. Не избежал этой участи и мой язык, хотя он конечно вылетает с помощью своих встроенных средств, а основное приложение продолжает свою работу. Но тем не менее. Какие у нас могут быть выходы из положения?

В целом моё предложение отдаёт парадигмой разработчиков компилятора GCC, поэтому хочу с вами посоветоваться. Итак, компилятор, допустим видит, что вызвали мемсет, зануляющий класс извнутри:

C++ Source Code:
1
Foo :: Foo()
2
{
3
  memset( this, 0, sizeof( *this ));
4
}

Он конечно будет ориентироваться не по ключевому слову this, а по началу указателя и размеру зануляемых данных. Но выловить подобный вызов элементарно. Итак, какие у нас варианты:

1. если в классе есть виртуальные методы - вывести варнинг, что будет бида
2. автоматически сдвинуть указатель на начало пользовательских данных
3. ничего не делать, как MSVC и как оно сейчас
4. свой вариант?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 03-02-2023 в 12:39:

Давно ничего не писал, немного отчитаюсь о проделанной работе, за которую автор, как известно - маладец.

1. сделаны шаблоны функций (до этого были только шаблоны классов)
2. переписан парсер выражений, приведён к стандарту С++, во всяком случае в плане приоритетов.
3. сделаны операторы и их перегрузка, включая new и delete, что в рамках виртуальной машины приобретает дополнительный смысловой контекст, о чём я непременно расскажу позже.
4. исправлено множество мелких ошибок, которые не выявлялись никакими юнит-тестами (их вообще правильнее называть регрессионные тесты), но стали попадаться при работе с реальными исходниками.

Осталось внедрить в язык последнюю конструкцию, которая есть в С++, а у меня пока ещё нет - это исключения. По идее на виртуальной машине такое должно реализовываться даже проще чем на С++ - заводим ещё один стек для исключений и дело в шляпе. Но проблема определения деструкторов, которые должны быть вызваны от этого никуда не исчезает, конечно.

Начал разбираться как устроен синтаксис. И выяснилось прекрасное. Есть две никак не связанные системы обработки исключений. Первая представлена словами: try, catch, throw, а вторая словами __try, __except, __finally. Особой пикантности добавляет тот факт, что в первом обработчике блока finally нет вообще. Уж не знаю, то ли это недоработка шестой студии, то ли соблюдение стандарта. Однако вот на сайте Мелкософта: https://learn.microsoft.com/ru-ru/c...p?view=msvc-170
Про него тоже ни слова. Это тем более интересно, если учесть, что в VCL-библиотеке наоборот всё держится именно на связке try, catch, finally
Мне кажется тут имеет место какое-то наслоение совместимости.
Надо выработать единый синтаксис, ну чтобы не путаться.

Добавлено 03-02-2023 в 13:54:

ЗЫ. Я чёт подумал, мож мне эти деструкторы просто коллекционировать в массив, а вызывать вручную, не бегая по коду и не проверяя, где они там должны быть вызваны? Хотя наверное нечто подобное и так делается, а при нормальной работе время уходит на то, чтобы найти указатель на очередной объект и выбросить его из списка при нормальном вызове деструктора. Ну что-то такое вообщем. Это пока просто размышления, т.к. я еще недостаточно погрузился в проблему.

Добавлено 03-02-2023 в 15:15:

Кажется дошло. Меня сбило с толку то, что в Делфи поддерживаются конструкции из трёх ключевых слов - try, except, finally, тогда как в С++ - только конструкции из двух слов, причём ключевого слова finally в механизме обработки исключений С++ нет. Оно есть только в микрософтовском расширении механизма обработки исключений для С, судя по всему построенному на лонг-джампах. Второй тип, как я понимаю, никаким-таким вызовом деструкторов не занимается и вообще про них ничего не знает.
А значит должен быть чуть более быстрым чем нативный С++ обработчик.
https://learn.microsoft.com/ru-ru/c...t?view=msvc-170

Добавлено 03-02-2023 в 15:19:

А, вот, есть ещё слово __leave, которое сразу прыгает на секцию __finally.
Но это механизм для управления нормальным потоком выполнения, т.к. никаких исключений при этом не бросается. Просто удобный выход из цепочки вызванных функций.

Добавлено 03-02-2023 в 15:39:

Возможно далеко не всем (хотя кого я обманываю? практически никому) не интересно то, что я здесь пишу, поэтому для обычных пользователей тоже кое-что расскажу. Вчера я провёл одну из заключительных оптимизаций выполнения кода виртуальной машины и получил производительность, которая меня более или менее устроила. Если подходить к замерам в сугубо синтетических тестах, ну например таких, как итерация цикла на 10-20 миллионов, то виртуальная машина сливает С++ без вариантов. Раз в 10 медленее, а может быть и в сто. Однако, когда речь идёт о выполнении реального кода, всё далеко не так однозначно. Ведь мы так или иначе обращаемся к каким-то тяжёлым функциям, например к вызову отрисовки треугольников на экране, к открытию\чтению файла, а это всё делает запрос в системные вызовы и конечная скорость работы зачастую определяется именно временем работы этих вызовов, а не скоростью самой виртуальной машины. Так вот, по моим прикидкам, в реальных задачах, она у меня медленее ну где-то на треть реального кода. Разумеется с оговоркой, что виртуальная машина выполняет только тот код, который предзначен для модификации пользователем и поэтому на фоне остального кода, его сравнительно немного. Именно поэтому падение производительности столь незначительное и более чем приемлимое. Я опасался что будет просадка в 5-10 раз.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 03-02-2023 в 13:17:

Цитата:
Дядя Миша писал:
Возможно далеко не всем (хотя кого я обманываю? практически никому) не интересно то, что я здесь пишу,


Да просто не понятно вообще что это, и зачем оно нужно. Мы такие хитроумные конструкции не юзаем

Цитата:
Дядя Миша писал:
Раз в 10 медленее, а может быть и в сто.


Ну так же будет возможность скомпилировать его в обычный бинарный код? Например как в Юнити. Можно и ВМ юзать, а можно просто в бинарники собрать.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 03-02-2023 в 15:44:

Цитата:
FiEctro писал:
Ну так же будет возможность скомпилировать его в обычный бинарный код?

Нет конечно. Или ты имеешь в виду JIT?
Если что-то можно можно собрать в "обычный бинарный файл", значит все возможности и удобства виртуальной машины идут по звезде.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 03-02-2023 в 15:47:

Дядя Миша
Я про это: https://docs.unity3d.com/Manual/IL2CPP.html

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 03-02-2023 в 16:46:

Ну там сишарп, я не знаю что они в очередной раз выдумали.

Добавлено 03-02-2023 в 19:32:

Вообще конечно интересные дела с этими исключениями. Судя по всему существует два типа обработчика исключений.
Первый - классический, когда стек разматывается обратно и мы выходим из блока try. Ну а дальше по ситуации вызываем либо секцию __except либо секцию __finally. Причём секция __finally будет вызвана в любом случае, т.к. это некий аналог ручного деструктора. В С++ этой секции нет. Почему?
Ну очевидно потому что исключения в С++ самостоятельно и корректно вызывают все деструкторы из всего стека, который они успели накопить на момент проброса исключения или вызова leave; Технически какой сигнал бросать совершенно не важно, исключения это просто очередной механизм обработки событий, эвенты в который могут поступать с разных сторон.
Таким образом становится понятно, что никакого смысла в секции finally попросту нет - всё что было выделено внутри вызванных функций будет корректно уничтожено вызовом деструкторов (в чистом Си не будет сделано вообще ничего), а то что было выделено на одном уровне с блоком try может быть прекрасно освобождено вообще безо всяких дополнительных секций.
Другой конечно вопрос, а как дать программе понять, что нам не нужно бросать исключения, а просто иногда нужен досрочный выход?

Добавлено 03-02-2023 в 19:46:

А, вон оно что оказывается. __try, __except, __finally - это SEH.
А try catch throw - это С++. Теперь понятно.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 09-02-2023 в 11:16:

https://twitter.com/BinaryImpactG/s...883380281876480
https://a.radikal.host/2023/02/09/FoWjni2X0AEJMx7.png

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 09-02-2023 в 12:43:

Это чего?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 09-02-2023 в 13:35:

Дядя Миша
Там написано.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 09-02-2023 в 14:31:

Непонятна.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 10-02-2023 в 05:47:

Дядя Миша
Я так понял получает доступ к последнему индексу в листе.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 10-02-2023 в 09:53:

В шарпе класс массива встроеный жи. А у меня можно добавить новый метод, и например назвать его top. По длине написания примерно тоже самое, но нагляднее. Но можно и в операторе доступа захэндлить значение -1, например.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 15-02-2023 в 07:53:

Минутка прекрасного

Продемонстрирую во что превращается вот эта функция

C++ Source Code:
1
void load_identity( void )
2
{
3
  mat[0] = vec3( 1.0f, 0.0f, 0.0f );
4
  mat[1] = vec3( 0.0f, 1.0f, 0.0f );
5
  mat[2] = vec3( 0.0f, 0.0f, 1.0f );
6
  mat[3] = vec3( 0.0f, 0.0f, 0.0f );
7
}

После компиляции. Т.е. как её видит интерпретатор виртуальной машины:
C++ Source Code:
1
87.ADD_P: stack[12]( xform* <RESULT> = '3373108' ) = stack[0]( CBaseEntity* this = '3372528' ) + heap[30684]( xform m_local = '580' );
2
88.PUSH_P: stack[52] = stack[12]( xform* <TYPECAST> = '3373108' );
3
89.OBJECT_CALL: xform::load_identity( locals 108, args 1, size 4 );
4
0.ADD_P: stack[4]( vec3[4]* <RESULT> = '3373108' ) = stack[0]( xform* this = '3373108' ) + heap[11568]( vec3[4] mat = '0' );
5
1.CHECKRANGE: heap[208]( int <IMMEDIATE> = '0' ) >= heap[208]( int <IMMEDIATE> = '0' ) < heap[372]( int <IMMEDIATE> = '4' );
6
2.ADD_P: stack[8]( vec3* <RESULT> = '3373108' ) = stack[4]( vec3[4] <TYPECAST> = '3373108' ) + heap[208]( int <IMMEDIATE> = '0' );
7
3.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006512' ) = &stack[12]( <TEMPOBJECT> );
8
4.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006512' );
9
5.PUSH_F: stack[112] = heap[7140]( float <IMMEDIATE> = '1' );
10
6.PUSH_F: stack[116] = heap[2948]( float <IMMEDIATE> = '0' );
11
7.PUSH_F: stack[120] = heap[2948]( float <IMMEDIATE> = '0' );
12
8.OBJECT_CALL: vec3::ctor( locals 28, args 4, size 16 );
13
0.ADD_P: stack[16]( float* <RESULT> = '283006512' ) = stack[0]( vec3* this = '283006512' ) + heap[3340]( float x = '0' );
14
1.STORE_F: stack[16]->address[283006512]->( float <TYPECAST> = '1' ) = stack[4]( float a0 = '1' );
15
2.ADD_P: stack[20]( float* <RESULT> = '283006516' ) = stack[0]( vec3* this = '283006512' ) + heap[3344]( float y = '4' );
16
3.STORE_F: stack[20]->address[283006516]->( float <TYPECAST> = '0' ) = stack[8]( float a1 = '0' );
17
4.ADD_P: stack[24]( float* <RESULT> = '283006520' ) = stack[0]( vec3* this = '283006512' ) + heap[3348]( float z = '8' );
18
5.STORE_F: stack[24]->address[283006520]->( float <TYPECAST> = '0' ) = stack[12]( float a2 = '0' );
19
6.RETURN: void;
20
9.PUSH_P: stack[108] = stack[8]( vec3* <TYPECAST> = '3373108' );
21
10.TAKE_ADDR: stack[28]( const vec3* <RESULT> = '283006512' ) = &stack[12]( <TEMPOBJECT> );
22
11.PUSH_P&: stack[112] = stack[28]( const vec3* <RESULT> = '283006512' );
23
12.OBJECT_CALL: vec3::=( locals 32, args 2, size 8 );
24
0.ADD_P: stack[8]( float* <RESULT> = '3373108' ) = stack[0]( vec3* this = '3373108' ) + heap[3340]( float x = '0' );
25
1.ADD_P: stack[12]( float* <RESULT> = '283006512' ) = stack[4]( vec3 <TYPECAST> = '283006512' ) + heap[3340]( float x = '0' );
26
2.STORE_F: stack[8]->address[3373108]->( float <TYPECAST> = '1' ) = stack[12]->address[283006512]->( float <TYPECAST> = '1' );
27
3.ADD_P: stack[16]( float* <RESULT> = '3373112' ) = stack[0]( vec3* this = '3373108' ) + heap[3344]( float y = '4' );
28
4.ADD_P: stack[20]( float* <RESULT> = '283006516' ) = stack[4]( vec3 <TYPECAST> = '283006512' ) + heap[3344]( float y = '4' );
29
5.STORE_F: stack[16]->address[3373112]->( float <TYPECAST> = '0' ) = stack[20]->address[283006516]->( float <TYPECAST> = '0' );
30
6.ADD_P: stack[24]( float* <RESULT> = '3373116' ) = stack[0]( vec3* this = '3373108' ) + heap[3348]( float z = '8' );
31
7.ADD_P: stack[28]( float* <RESULT> = '283006520' ) = stack[4]( vec3 <TYPECAST> = '283006512' ) + heap[3348]( float z = '8' );
32
8.STORE_F: stack[24]->address[3373116]->( float <TYPECAST> = '0' ) = stack[28]->address[283006520]->( float <TYPECAST> = '0' );
33
9.STORE_P&: heap[0]( int <RETURN> = '3373108' ) = stack[0]( vec3* <TYPECAST> = '3373108' );
34
10.RETURN: void;
35
13.STORE_P&: stack[32]( vec3* <RESULT> = '3373108' ) = heap[0]( int <RETURN> = '3373108' );
36
14.ADD_P: stack[36]( vec3[4]* <RESULT> = '3373108' ) = stack[0]( xform* this = '3373108' ) + heap[11568]( vec3[4] mat = '0' );
37
15.CHECKRANGE: heap[208]( int <IMMEDIATE> = '0' ) >= heap[104]( int <IMMEDIATE> = '1' ) < heap[372]( int <IMMEDIATE> = '4' );
38
16.ADD_P: stack[40]( vec3* <RESULT> = '3373120' ) = stack[36]( vec3[4] <TYPECAST> = '3373108' ) + heap[3656]( int <IMMEDIATE> = '12' );
39
17.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006544' ) = &stack[44]( <TEMPOBJECT> );
40
18.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006544' );
41
19.PUSH_F: stack[112] = heap[2948]( float <IMMEDIATE> = '0' );
42
20.PUSH_F: stack[116] = heap[7140]( float <IMMEDIATE> = '1' );
43
21.PUSH_F: stack[120] = heap[2948]( float <IMMEDIATE> = '0' );
44
22.OBJECT_CALL: vec3::ctor( locals 28, args 4, size 16 );
45
0.ADD_P: stack[16]( float* <RESULT> = '283006544' ) = stack[0]( vec3* this = '283006544' ) + heap[3340]( float x = '0' );
46
1.STORE_F: stack[16]->address[283006544]->( float <TYPECAST> = '0' ) = stack[4]( float a0 = '0' );
47
2.ADD_P: stack[20]( float* <RESULT> = '283006548' ) = stack[0]( vec3* this = '283006544' ) + heap[3344]( float y = '4' );
48
3.STORE_F: stack[20]->address[283006548]->( float <TYPECAST> = '1' ) = stack[8]( float a1 = '1' );
49
4.ADD_P: stack[24]( float* <RESULT> = '283006552' ) = stack[0]( vec3* this = '283006544' ) + heap[3348]( float z = '8' );
50
5.STORE_F: stack[24]->address[283006552]->( float <TYPECAST> = '0' ) = stack[12]( float a2 = '0' );
51
6.RETURN: void;
52
23.PUSH_P: stack[108] = stack[40]( vec3* <TYPECAST> = '3373120' );
53
24.TAKE_ADDR: stack[28]( const vec3* <RESULT> = '283006544' ) = &stack[44]( <TEMPOBJECT> );
54
25.PUSH_P&: stack[112] = stack[28]( const vec3* <RESULT> = '283006544' );
55
26.OBJECT_CALL: vec3::=( locals 32, args 2, size 8 );
56
0.ADD_P: stack[8]( float* <RESULT> = '3373120' ) = stack[0]( vec3* this = '3373120' ) + heap[3340]( float x = '0' );
57
1.ADD_P: stack[12]( float* <RESULT> = '283006544' ) = stack[4]( vec3 <TYPECAST> = '283006544' ) + heap[3340]( float x = '0' );
58
2.STORE_F: stack[8]->address[3373120]->( float <TYPECAST> = '0' ) = stack[12]->address[283006544]->( float <TYPECAST> = '0' );
59
3.ADD_P: stack[16]( float* <RESULT> = '3373124' ) = stack[0]( vec3* this = '3373120' ) + heap[3344]( float y = '4' );
60
4.ADD_P: stack[20]( float* <RESULT> = '283006548' ) = stack[4]( vec3 <TYPECAST> = '283006544' ) + heap[3344]( float y = '4' );
61
5.STORE_F: stack[16]->address[3373124]->( float <TYPECAST> = '1' ) = stack[20]->address[283006548]->( float <TYPECAST> = '1' );
62
6.ADD_P: stack[24]( float* <RESULT> = '3373128' ) = stack[0]( vec3* this = '3373120' ) + heap[3348]( float z = '8' );
63
7.ADD_P: stack[28]( float* <RESULT> = '283006552' ) = stack[4]( vec3 <TYPECAST> = '283006544' ) + heap[3348]( float z = '8' );
64
8.STORE_F: stack[24]->address[3373128]->( float <TYPECAST> = '0' ) = stack[28]->address[283006552]->( float <TYPECAST> = '0' );
65
9.STORE_P&: heap[0]( int <RETURN> = '3373120' ) = stack[0]( vec3* <TYPECAST> = '3373120' );
66
10.RETURN: void;
67
27.STORE_P&: stack[56]( vec3* <RESULT> = '3373120' ) = heap[0]( int <RETURN> = '3373120' );
68
28.ADD_P: stack[60]( vec3[4]* <RESULT> = '3373108' ) = stack[0]( xform* this = '3373108' ) + heap[11568]( vec3[4] mat = '0' );
69
29.CHECKRANGE: heap[208]( int <IMMEDIATE> = '0' ) >= heap[376]( int <IMMEDIATE> = '2' ) < heap[372]( int <IMMEDIATE> = '4' );
70
30.ADD_P: stack[64]( vec3* <RESULT> = '3373132' ) = stack[60]( vec3[4] <TYPECAST> = '3373108' ) + heap[7476]( int <IMMEDIATE> = '24' );
71
31.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006568' ) = &stack[68]( <TEMPOBJECT> );
72
32.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006568' );
73
33.PUSH_F: stack[112] = heap[2948]( float <IMMEDIATE> = '0' );
74
34.PUSH_F: stack[116] = heap[2948]( float <IMMEDIATE> = '0' );
75
35.PUSH_F: stack[120] = heap[7140]( float <IMMEDIATE> = '1' );
76
36.OBJECT_CALL: vec3::ctor( locals 28, args 4, size 16 );
77
0.ADD_P: stack[16]( float* <RESULT> = '283006568' ) = stack[0]( vec3* this = '283006568' ) + heap[3340]( float x = '0' );
78
1.STORE_F: stack[16]->address[283006568]->( float <TYPECAST> = '0' ) = stack[4]( float a0 = '0' );
79
2.ADD_P: stack[20]( float* <RESULT> = '283006572' ) = stack[0]( vec3* this = '283006568' ) + heap[3344]( float y = '4' );
80
3.STORE_F: stack[20]->address[283006572]->( float <TYPECAST> = '0' ) = stack[8]( float a1 = '0' );
81
4.ADD_P: stack[24]( float* <RESULT> = '283006576' ) = stack[0]( vec3* this = '283006568' ) + heap[3348]( float z = '8' );
82
5.STORE_F: stack[24]->address[283006576]->( float <TYPECAST> = '1' ) = stack[12]( float a2 = '1' );
83
6.RETURN: void;
84
37.PUSH_P: stack[108] = stack[64]( vec3* <TYPECAST> = '3373132' );
85
38.TAKE_ADDR: stack[28]( const vec3* <RESULT> = '283006568' ) = &stack[68]( <TEMPOBJECT> );
86
39.PUSH_P&: stack[112] = stack[28]( const vec3* <RESULT> = '283006568' );
87
40.OBJECT_CALL: vec3::=( locals 32, args 2, size 8 );
88
0.ADD_P: stack[8]( float* <RESULT> = '3373132' ) = stack[0]( vec3* this = '3373132' ) + heap[3340]( float x = '0' );
89
1.ADD_P: stack[12]( float* <RESULT> = '283006568' ) = stack[4]( vec3 <TYPECAST> = '283006568' ) + heap[3340]( float x = '0' );
90
2.STORE_F: stack[8]->address[3373132]->( float <TYPECAST> = '0' ) = stack[12]->address[283006568]->( float <TYPECAST> = '0' );
91
3.ADD_P: stack[16]( float* <RESULT> = '3373136' ) = stack[0]( vec3* this = '3373132' ) + heap[3344]( float y = '4' );
92
4.ADD_P: stack[20]( float* <RESULT> = '283006572' ) = stack[4]( vec3 <TYPECAST> = '283006568' ) + heap[3344]( float y = '4' );
93
5.STORE_F: stack[16]->address[3373136]->( float <TYPECAST> = '0' ) = stack[20]->address[283006572]->( float <TYPECAST> = '0' );
94
6.ADD_P: stack[24]( float* <RESULT> = '3373140' ) = stack[0]( vec3* this = '3373132' ) + heap[3348]( float z = '8' );
95
7.ADD_P: stack[28]( float* <RESULT> = '283006576' ) = stack[4]( vec3 <TYPECAST> = '283006568' ) + heap[3348]( float z = '8' );
96
8.STORE_F: stack[24]->address[3373140]->( float <TYPECAST> = '1' ) = stack[28]->address[283006576]->( float <TYPECAST> = '1' );
97
9.STORE_P&: heap[0]( int <RETURN> = '3373132' ) = stack[0]( vec3* <TYPECAST> = '3373132' );
98
10.RETURN: void;
99
41.STORE_P&: stack[80]( vec3* <RESULT> = '3373132' ) = heap[0]( int <RETURN> = '3373132' );
100
42.ADD_P: stack[84]( vec3[4]* <RESULT> = '3373108' ) = stack[0]( xform* this = '3373108' ) + heap[11568]( vec3[4] mat = '0' );
101
43.CHECKRANGE: heap[208]( int <IMMEDIATE> = '0' ) >= heap[824]( int <IMMEDIATE> = '3' ) < heap[372]( int <IMMEDIATE> = '4' );
102
44.ADD_P: stack[88]( vec3* <RESULT> = '3373144' ) = stack[84]( vec3[4] <TYPECAST> = '3373108' ) + heap[3900]( int <IMMEDIATE> = '36' );
103
45.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006592' ) = &stack[92]( <TEMPOBJECT> );
104
46.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006592' );
105
47.PUSH_F: stack[112] = heap[2948]( float <IMMEDIATE> = '0' );
106
48.PUSH_F: stack[116] = heap[2948]( float <IMMEDIATE> = '0' );
107
49.PUSH_F: stack[120] = heap[2948]( float <IMMEDIATE> = '0' );
108
50.OBJECT_CALL: vec3::ctor( locals 28, args 4, size 16 );
109
0.ADD_P: stack[16]( float* <RESULT> = '283006592' ) = stack[0]( vec3* this = '283006592' ) + heap[3340]( float x = '0' );
110
1.STORE_F: stack[16]->address[283006592]->( float <TYPECAST> = '0' ) = stack[4]( float a0 = '0' );
111
2.ADD_P: stack[20]( float* <RESULT> = '283006596' ) = stack[0]( vec3* this = '283006592' ) + heap[3344]( float y = '4' );
112
3.STORE_F: stack[20]->address[283006596]->( float <TYPECAST> = '0' ) = stack[8]( float a1 = '0' );
113
4.ADD_P: stack[24]( float* <RESULT> = '283006600' ) = stack[0]( vec3* this = '283006592' ) + heap[3348]( float z = '8' );
114
5.STORE_F: stack[24]->address[283006600]->( float <TYPECAST> = '0' ) = stack[12]( float a2 = '0' );
115
6.RETURN: void;
116
51.PUSH_P: stack[108] = stack[88]( vec3* <TYPECAST> = '3373144' );
117
52.TAKE_ADDR: stack[28]( const vec3* <RESULT> = '283006592' ) = &stack[92]( <TEMPOBJECT> );
118
53.PUSH_P&: stack[112] = stack[28]( const vec3* <RESULT> = '283006592' );
119
54.OBJECT_CALL: vec3::=( locals 32, args 2, size 8 );
120
0.ADD_P: stack[8]( float* <RESULT> = '3373144' ) = stack[0]( vec3* this = '3373144' ) + heap[3340]( float x = '0' );
121
1.ADD_P: stack[12]( float* <RESULT> = '283006592' ) = stack[4]( vec3 <TYPECAST> = '283006592' ) + heap[3340]( float x = '0' );
122
2.STORE_F: stack[8]->address[3373144]->( float <TYPECAST> = '0' ) = stack[12]->address[283006592]->( float <TYPECAST> = '0' );
123
3.ADD_P: stack[16]( float* <RESULT> = '3373148' ) = stack[0]( vec3* this = '3373144' ) + heap[3344]( float y = '4' );
124
4.ADD_P: stack[20]( float* <RESULT> = '283006596' ) = stack[4]( vec3 <TYPECAST> = '283006592' ) + heap[3344]( float y = '4' );
125
5.STORE_F: stack[16]->address[3373148]->( float <TYPECAST> = '0' ) = stack[20]->address[283006596]->( float <TYPECAST> = '0' );
126
6.ADD_P: stack[24]( float* <RESULT> = '3373152' ) = stack[0]( vec3* this = '3373144' ) + heap[3348]( float z = '8' );
127
7.ADD_P: stack[28]( float* <RESULT> = '283006600' ) = stack[4]( vec3 <TYPECAST> = '283006592' ) + heap[3348]( float z = '8' );
128
8.STORE_F: stack[24]->address[3373152]->( float <TYPECAST> = '0' ) = stack[28]->address[283006600]->( float <TYPECAST> = '0' );
129
9.STORE_P&: heap[0]( int <RETURN> = '3373144' ) = stack[0]( vec3* <TYPECAST> = '3373144' );
130
10.RETURN: void;
131
55.STORE_P&: stack[104]( vec3* <RESULT> = '3373144' ) = heap[0]( int <RETURN> = '3373144' );
132
56.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006592' ) = &stack[92]( <TEMPOBJECT> );
133
57.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006592' );
134
58.OBJECT_CALL: vec3::dtor( locals 4, args 1, size 4 );
135
0.RETURN: void;
136
59.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006568' ) = &stack[68]( <TEMPOBJECT> );
137
60.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006568' );
138
61.OBJECT_CALL: vec3::dtor( locals 4, args 1, size 4 );
139
0.RETURN: void;
140
62.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006544' ) = &stack[44]( <TEMPOBJECT> );
141
63.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006544' );
142
64.OBJECT_CALL: vec3::dtor( locals 4, args 1, size 4 );
143
0.RETURN: void;
144
65.TAKE_ADDR: stack[24]( vec3* <RESULT> = '283006512' ) = &stack[12]( <TEMPOBJECT> );
145
66.PUSH_P: stack[108] = stack[24]( vec3* <RESULT> = '283006512' );
146
67.OBJECT_CALL: vec3::dtor( locals 4, args 1, size 4 );
147
0.RETURN: void;
148
68.RETURN: void;

148 инструкций. Правда это дебаг-сборка, в релизе инструкций будет поменьше.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 15-02-2023 в 08:21:

Это ассемблер? Значит всё же можно скомпилировать как обычный код?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 15-02-2023 в 09:08:

Это мой собственный ассемблер. Он не совместим с обычным.

Цитата:
FiEctro писал:
Значит всё же можно скомпилировать как обычный код?

Мой язык использует конструкции, которые невозможны в других языках.
Точнее возможны, но вместо одного красивого вызова придётся ручками много чего сделать. Ну собственно, языки для того и нужны - чтобы освободить от лишней работы. А больше они ни для чего не нужны.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 01-03-2023 в 11:30:

Ну вот товарищи, в процессе портирования энтить на новый язык ожидаемо столкнулся с большим геморроем, который на С++ вообще не имеет изящного решения. А именно - представление энумераторов в качестве имён.
Пока мы хотим от них иметь только номера - проблемы нет. Но стоит нам захотить получить ассоциированную связку имя<->уникальный идентификатор, то начинаются проблемы. Которые решают обычно костылём. Напомню как это сделано в той же халфе:

C++ Source Code:
1
typedef enum
2
{
3
  ACT_RESET = 0,		// Set m_Activity to this invalid value to force a reset to m_IdealActivity
4
  ACT_IDLE = 1,
5
  ACT_GUARD,
6
  ACT_WALK,
7
  ACT_RUN,
8
  ACT_FLY,

Это наши идентификаторы. То есть уникальные номера. Однако нам по смыслу нужны не только номера, но ещё и имена этих номеров. И тут уже начинаются проблемы. С++ не располагает средствами для их автоматической ассоциации. Поэтому заводим структурку конверсии:
C++ Source Code:
1
typedef struct
2
{
3
  int		type;
4
  const char	*name;
5
} activity_map_t;

В принципе это вальвовский избыточный говнокод и int type тут вообще не нужен, т.к. он совпадает с номером индекса в массиве. Я просто привожу оригинальный код. Дальше через макрос!!! инициализируем его вот так:
C++ Source Code:
1
#define _A( a ) { a, #a }
2
 
3
activity_map_t activity_map[] =
4
{
5
  _A( ACT_RESET ),
6
  _A( ACT_IDLE ),
7
  _A( ACT_GUARD ),
8
  _A( ACT_WALK ),
9
  _A( ACT_RUN ),
10
  _A( ACT_FLY ),

Т.е. никаких других средств в С++ для превращения имени переменной в строку попросту нет. Специально выделил жирным, потому что имена и строки в парадигме того же С++ это разные вещи.

Понятное дело что это вообще не удобно. В HL2, как вы знаете отошли от стратегии жесткой привязки актов к индексам, потому что ваша анимационно-зависимая модель фактически прибита гвоздями к какому-то грёбанному энуму в игровом коде. Это само по себе не представляло бы проблемы, если бы не было точно такой же привязки к этому энуму - в компиляторе студиомоделей. Теперь на минутку представим, что они отличаются. Ну и всё поломалось. С именами, понятное дело, такое не произойдет. Собственно в XashNT активность задаётся именами, однако встаёт вопрос как описать этот долбанный стейт. Даже если учесть что в данном случае нам вообще не нужна таблица, а достаточно лишь имён - их ведь надо проинициализировать! То есть типичная форма инициализации будет выглядеть как-то так:
C++ Source Code:
string ACT_RESET = "ACT_RESET";

Это конечно можно обвернуть в макросы, аналогичные вышеприведённому, но для компилятора эти строчки так и останутся кучей несвязанных. Они ничего не будет знать об их группировке и принадлежности, чтобы, например избежать ненадлежащего приведения типов. А это было бы весьма полезно. Я предлагаю следующее решение данной проблемы:
C++ Source Code:
1
stringtable Activity
2
{
3
  ACT_RESET,
4
  ACT_IDLE,
5
  ACT_GUARD,
6
  ACT_WALK,
7
  ACT_RUN,
8
  ACT_FLY,

Во первых строчки группируются по принадлежности к группе Activity тем или иным образом. Даже если я не сделаю этого сейчас, это всегда можно будет ввести чуть позднее. По аналогии с тем же enumclass. Инициализация этих строчек происходит автоматически - их же именами.
Поскольку мой язык работает не с явными дублирующимися в памяти строками, а с их идентификаторами, то каждая такая строка автоматически получает свой идентификатор и может быть без проблем преобразована в целое число, отличное от ноля, если это вдруг понадобится. Так же яызк поддерживает конструкции switch-case со строками. Т.е. для программиста это будет выглядеть именно как работа с энумератором.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 02-03-2023 в 05:19:

Вы всё еще можете предложить тут что-то улучшить. Например вместо ключевого слова stringtable - какое-то другое.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 02-03-2023 в 09:18:

Почему просто массив не использовать? Или Листы из шарпов.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено nemyax 02-03-2023 в 09:31:

Цитата:
Дядя Миша писал:
для компилятора эти строчки так и останутся кучей несвязанных. Они ничего не будет знать об их группировке и принадлежности

В неймспейс завернуть можно.


Отправлено Дядя Миша 02-03-2023 в 09:48:

Цитата:
FiEctro писал:
Почему просто массив не использовать?

Перечитай внимательно. Можно и массив конечно, но есть случаи.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 02-03-2023 в 10:55:

Так, а зачем вообще тащить эти костыли в движок? Все анимации лучше всего хранить в префабах (небольшие скриптовые файлы содержащие в себе всю логику взаимодействия анимаций, эвенеты, нарезка длинных анимаций на короткие, смешивание, скорость воспроизведения, цикличность воспроизведения, ИК кости и прочие констрейнты с их настройками, и т.д.), а из кода уже просто обращаться к этому компоненту как к отдельному классу и его Стейтам.

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 02-03-2023 в 13:04:

Ты вообще ничего не понял

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 06-03-2023 в 05:50:

Небольшая демонстрация того, на каких тоненьких ниточках в С++ держится детектирование тех или иных конструкций. В чистом Си, напомню, таких ситуаций не могло возникнуть в принципе. Напомню также, что компилятор в первую очередь ориентируется по синтаксису и только во вторую - по типу, причём синтаксис имеет определяющее значение.

C++ Source Code:
1
if( ExtractBbox( m_sequence, bounds ))
2
{
3
  xform transform( g_vecZero, vec3( 0.0f, m_absangles.y, 0.0f )); <--
4
  bounds = transform * bounds;
5
  UTIL_SetSize( this, bounds.mins, bounds.maxs );
6
}

Конструкция, помеченная стрелочкой, до вчерашнего дня ошибочно трактовалась компилятором как объявление новой функции. А поскольку функция внутри функции невозможна, то естественно выпадала ошибка. Почему так происходило? Первые два токена в этом плане не могут служить чётким критерием, при условии, что первый токен - реально существующий тип, а второй - имя. Дальше у нас есть ветвление, либо это переменная (неважно в сущности, локальная или глобальная), либо действительно объявление новой функции. В чистом Си, наличие открывающей круглой скобки уже явным образом говорило - перед нами объявление новой функции. В С++ это не так, ведь это может быть вызов кастомного конструктора. То есть, даже прочитав скобку, мы всё еще не можем определить что перед нами. Надо читать то что внутри скобок. Я не знаю как это устроено в самом С++, но я лично делаю лукап на несколько токенов вперёд (обычно на один, не больше), чтобы оценить обстановку, а потом возвращаюсь на текущее место. Так вот, в моменте ветвления, когда токен ( уже прочитан, а следующий находится в памяти, на первый взгляд мы можем просто посмотреть что это за токен и сделать выводы. Если токен это целое число, дробное число, строка или же пунктуация, то это 100% вызов конструктора. Следующая проверка - на наличие модификаторов или declspec. Если они есть - значит перед нами декларация новой функции. Разумеется они быть не обязаны. Следующая проверка на то, что следующий токен не является известным компилятору типом. И тут всё и падает с ошибкой. Потому что g_vecZero выглядит вот так:
C++ Source Code:
#define g_vecZero	vec3( 0.0f )

Таким образом компилятор читает слово vec3, находит такой тип и думает - это объявление функции. Ну и дальше идёт ругань про невозможность объявления функции внутри функции. И невозможность распарсить её аргументы. А потому что кроме вызова пользовательских конструкторов в С++ есть ещё r-value объекты, которые добавляют ещё хаоса. И теперь к типу дополнительно надо проверять так же наличие очередной открывающей круглой скобки, чтобы убедиться что перед нами.
А ведь в теории конструктор может быть шаблонной функцией...

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 06-03-2023 в 06:06:

Цитата:
Дядя Миша писал:
Конструкция, помеченная стрелочкой, до вчерашнего дня ошибочно трактовалась компилятором как объявление новой функции

Но это и есть объявление новой функции. Согласно принципу MVP в плюсах, "всё, что выглядит как объявление функции, есть объявление функции".
Чтобы избежать этого, в С++11 имеется инициализация фигурными скобками. Ну или по классике:
C++ Source Code:
auto transform = xform(...);

Что абсолютно эквивалетно приведённому выше коду, но не выглядит как объявление функции.

__________________

xaerox on Vivino


Отправлено Дядя Миша 06-03-2023 в 06:09:

Цитата:
XaeroX писал:
всё, что выглядит как объявление функции, есть объявление функции

Да-да, а всё что крякает как утка, это гусь. Я решительно против такого подхода. Мне пролетарское чутьё подсказывает его ошибочность.

Добавлено 06-03-2023 в 09:09:

Цитата:
XaeroX писал:
Что абсолютно эквивалетно приведённому выше коду

Ты конечно же забыл, что программистов больше всего волнует, как бы им не дай бог не написать лишних букв, чтобы не устать и не перетрудиться.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 06-03-2023 в 08:17:

Дядя Миша
Ты можешь быть сколько угодно против, но в крестах это одно из краеугольных правил.

Добавлено 06-03-2023 в 03:17:

Цитата:
Дядя Миша писал:
Ты конечно же забыл, что программистов больше всего волнует, как бы им не дай бог не написать лишних букв

Ну это, наверное, те же, кто не оставляет комментариев.

__________________

xaerox on Vivino


Отправлено Дядя Миша 06-03-2023 в 10:08:

Цитата:
XaeroX писал:
"всё, что выглядит как объявление функции, есть объявление функции".

Осталось только определиться с критериями. Потому что единственным способом отдуплить объявление функции от вызова конструктора является анализ того что между скобками.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 06-03-2023 в 11:42:

Цитата:
Дядя Миша писал:
__xform transform( g_vecZero, vec3( 0.0f, m_absangles.y, 0.0f )); <--


Я пока не знаю так хорошо синтаксис, но что тут нелегального? Вызов функции, и задаёшь ей аргументы. Только мне не понятно что есть xform и зачем он тут? Тогда уж как то так myvar = xform.transform( g_vecZero, vec3( 0.0f, m_absangles.y, 0.0f ));

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 06-03-2023 в 13:35:

xform - это матрица размерностью 4х3.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 20-07-2024 в 08:46:

Возникла потребность сделать перегрузку макросов.
Насколько я понял ни одна студия так и не обзавелась этой полезной возможностью в явном виде. Везде какие-то костыли с variadic.
Интересно почему? Может я что-то упускаю из виду?
Но мне кажется сделать перегрузку просто по числу аргументов вполне себе реально. Будем попробовать.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 20-07-2024 в 09:16:

Хз, никогда не использовал перегрузку макросов.

Цитата:
Дядя Миша писал:
Насколько я понял ни одна студия так и не обзавелась этой полезной возможностью в явном виде. Везде какие-то костыли с variadic.


В блокнотике и такого нет

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 20-07-2024 в 09:34:

Ну кстати вот первый спорный момент. #undef будет удалять всю группу перегруженных макросов. В принципе #undef используется редко, так что я думаю это не должно привести к каким-либо проблемам.

В текущей кодобазе на шоте он у меня вообще так ни разу и не понадобился. Но можно впоследствии сделать расширенный ундеф, который будет считать кол-во аргументов, например.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 20-07-2024 в 16:23:

Чтож, наличие перегрузки макросов автоматически делает препроцессор более строгим к ошибкам, хотя по факту это всё соблюдалось и ранее.

Я вывел следующее правило наличия аргументов:

1. Если это макрос вида #define a или #define a b, то кол-во аргументов равно -1
2. Если это макрос вида #define a() то кол-во аргументов равно 0
3. Если это макрос вида #define foo( a, b, c ) то кол-во аргументов равно их кол-ву указанному пользователем. В данном случае три.

Здесь понятно и очевидно. Мы создаём лист наших макросов где под одинаковыми именами могут прятаться макросы с разным числом аргументов.
Иными словами сейчас можно объявить:

C++ Source Code:
#define foo
#define foo()
#define foo( a )


И это будет нашей перегрузкой. Если мы просто вызываем макрос для раскрытия в коде, то всё хорошо. Проблемы начинаются когда мы начинаем обращаться к нашему макросу средствами самого препроцессора. Для этого у нас есть следующие команды:
C++ Source Code:
1
#if
2
#ifdef
3
#ifndef
4
#elif
5
#undef

Тут уже намечается некоторое несоответствие причём в оригинальном препроцессоре. К примеру конструкцию #define foo( a ) бессмысленно проверять на #if. На #if проверяются вещи, типа #define foo 1 которые заведомо не имеют аргументов. В данном случае поиск макроса для условия #if будет вообще игнорировать те, что имеют аргументы. Тут логика не нарушется, всё в порядке. С остальными директивами некоторая неоднозначность присутствует. Как видно из примера выше мы объявили три перегруженных foo. Какой из них будет реагировать на команду #ifdef foo? Только #define foo!
Если мы хотим проверить наличие и остальных аргументов, то нам следует написать #ifdef foo( a ) к примеру. Но тут-то как раз и кроется засада.
Дело в том, что вот это вот a - оно там просто от балды. Парсеру всё равно что там будет, ему лишь надо посчитать кол-во аргументов.
Аналогичная ситуация и с undef. Т.е. некоторая неоднозначность будет присутствовать. Опять же команды препроцессора живут молча - если им что-то не удалось, не выводится никаких ошибок или предупреждений.

Добавлено 20-07-2024 в 19:23:

Надо заметить что это крайне непростое дело - перегрузка макросов.
Тут и совместимость мешает и сам факт что препроцессор нестрогий.
То есть условия #ifdef теперь ужесточаются но при этом сохраняют обратную совместимость. Пример:

C++ Source Code:
1
#define FOO( a )\
2
printf( "macro1: %d\n", a );
3
 
4
#define FOO( a, b )\
5
printf( "macro2: %d %d\n", a, b );
6
 
7
#define FOO( a, b, c )\
8
printf( "macro3: %d %d %d\n", a, b, c );
9
 
10
void main( void )
11
{
12
#ifdef FOO
13
  FOO( 1 );
14
#endif
15
 
16
#ifdef FOO
17
  FOO( 1, 2 );
18
#endif
19
 
20
#ifdef FOO
21
  FOO( 1, 2, 3 );
22
#endif
23
}

Ни одно из условий #ifdef выполнено не будет. Потому что препроцессор теперь считает что мы ищем объявление #define FOO. Т.е. здесь всегда осуществляется проверка на строгое соответствие и разумеется, меняется синтаксис.
C++ Source Code:
1
#define FOO( a )\
2
printf( "macro1: %d\n", a );
3
 
4
#define FOO( a, b )\
5
printf( "macro2: %d %d\n", a, b );
6
 
7
#define FOO( a, b, c )\
8
printf( "macro3: %d %d %d\n", a, b, c );
9
 
10
void main( void )
11
{
12
#ifdef FOO( 1 )
13
  FOO( 1 );
14
#endif
15
 
16
#ifdef FOO( 1, 2 )
17
  FOO( 1, 2 );
18
#endif
19
 
20
#ifdef FOO( 1, 2, 3 )
21
  FOO( 1, 2, 3 );
22
#endif
23
}

Этот код уже не прожуется ни Си ни С++ препроцессором - он просто не ожидает что после имени макроса ещё и аргументы. Причём, прошу заметить - их может и не быть. Тогда ищется декларация
#define FOO или #define FOO BAR. Но ведь никто никогда и не проверяет на #ifdef макросы с аргументами! Они служат вообще для другого.
Технически эта возможность есть и в старом препроцессоре, просто так никто не делает - это операция заведомо лишена смысла.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 06-08-2024 в 17:25:

Пришло время добавить в язык ещё одну очень важную вещь - Direct Member Initializers. Как вы знаете, можно инициализировать переменные, объявленные в глобальном пространстве и переменные, объявленные внутри функции, а вот переменные-члены класса нельзя проинициализировать прямо там же внутри описания класса. Конечно есть member initializer list, но вы представьте на что будет похожа запись, если в вашем классе десятки членов? И как не запутаться что и чем вы там проинициализировали.
Лично мне эта штука нужна для более удобной декларации абстрактных переменных, я не знаю как это правильно назвать. Ну вот помните в халфе была такая структурка как movevars_t ?
Там ещё эти переменные можно было сохранять в конфиг, они по сети пересылались и их можно было менять из консоли. Вот, при помощи Шота я хочу сделать такой абстрактный и универсальный механизм для объявления таких кваров. У меня в сущности уже есть все компоненты для этого, но нет объявления по дефолту и это весьма неудобно. То есть можно и обойтись, но будет некрасиво.

в С11 насколько я понимаю ввели вот такую уродливую конструкцию

C++ Source Code:
1
class CFoo
2
{
3
  int n = 7;
4
  std::string s{'a', 'b', 'c'};
5
};

Как вы видите атомарные переменные инициализируются через присвоение, а классы - через фигурные скобки. Собственно, оно и так и эдак плохо. Потому что никакой реальной инициализации в этом месте всё равно не происходит. Плюс тут ещё встаёт вопрос, как задавать bitfield при таком раскладе, но ладно. Мой поинт в том, чтобы инициализировать такие переменные как конструкторы. Ну то есть
C++ Source Code:
1
class CFoo
2
{
3
  int n( 7 );
4
  std::string s( 'a', 'b', 'c );
5
};

Вы уже догадались в чём тут сложность? Да, это очередной случай MVX.
Но ведь подобное же объявление возможно в глобальном пространстве или внутри функции. То есть это уже вполне решаемая проблема. Да и выглядит оно так аккуратнее, т.к. конструктор не ассоциируется с явным присвоением, да собственно и не должен. Единственный негативный момент - вы не сможете это проинициализировать с скобками без аргументов, т.е. (); Потому что компилятор тогда решит что вы объявили функцию. Но ведь и с объявлением переменных на стеке и в куче обстоит ровно так же! Мы просто не пишем эти скобки и вызывается конструктор по умолчанию. Так что я планирую придерживаться именно этого способа.
Единственный минус - так нельзя проинициализировать массив, но ведь и вне объявления класса его невозможно так проинициализировать. Следовательно нововведение не нарушает целостность языка, что лично для меня самое главное. Чтож, попробуем реализовать вышеописанное.

Добавлено 06-08-2024 в 19:30:

Любопытный момент отмечу. Как выяснилось, мне совсем не пришлось вводить в компилятор какие-то дополнительные проверки для подобной формы записи, всё необходимое уже существовало, достаточно было лишь добавить новое условие и всё корректно распарсилось. Но! В процессе имплементации мне пришла в голову ещё одна весьма важная мысль.
Как все мы знаем при объявлении функции можно писать так:

C++ Source Code:
void foo( void )

А можно вот так
C++ Source Code:
void foo()

Причём в С++ этот как бы не регламентируется, мол хотите так пишете, хотите эдак, разницы нет. А между прочим это весьма и весьма важный момент. Ведь нельзя же вызвать конструктор вот так:

C++ Source Code:
int foo( void );

Т.е. это у нас однозначное определение функции. А в С++ присутствует неоднозначность в этом плане. Правда бедные программисты, которые очень бояться перетрудится и написать несколько лишних букв в массе своей стараются не писать это слово void, даже несмотря на регулярные заявления о том, что 90% времени программист не пишет код, а читает его, ну а я знаю, что только тех кто любит труд - октрябятами зовут!
Поэтому я всегда прописывал слово void в объявлении функций без аргументов. Нет, если серъезно, мне кажется что так красивее выглядит, поэтому и писал. Ну а в С++ этот момент сломать видимо уже не могли.
Правда я хочу отметить что и мне его вовсе не надо ломать для правильного объявления этих конструкторов по умолчанию. Оно и так будет прекрасно работать, это просто наметка на будущее, чтобы избежать неоднозначности. Потому что в языке, парсер которого смотрит лишь на один токен вперёд имеет значение абсолютно всё. Это вам не Раст, который анализирует исходник целиком.

Добавлено 06-08-2024 в 20:25:

Новая фича готова. Пример кода:
C++ Source Code:
1
class vec3
2
{
3
  float	x, y, z;
4
public:
5
  vec3( float in_x, float in_y, float in_z )
6
  {
7
    x = in_x;
8
    y = in_y;
9
    z = in_z;
10
    Msg( "%s( %g %g %g )\n", nameof( this ), x, y, z );
11
  }
12
 
13
  vec3()
14
  {
15
    Msg( "%s()\n", nameof( this ));
16
  }
17
 
18
  virtual ~vec3() {}
19
};
20
 
21
class CObject
22
{
23
  vec3	origin( 10.0f, 20.0f, 30.0f );	// direct member initialization
24
  vec3	angles( 30.0f, 20.0f, 10.0f );	// direct member initialization
25
  vec3	scale;				// initialization by default
26
public:
27
  int	foo( 5 );				// direct member initialization
28
};
29
 
30
void main( void )
31
{
32
  CObject	test;
33
 
34
  Msg( "test.foo = %d\n", test.foo );
35
}

Результат запуска:
Цитата:

origin( 10 20 30 )
angles( 30 20 10 )
scale()
test.foo = 5

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 06-08-2024 в 23:20:

Цитата:
Дядя Миша писал:
Как вы знаете, можно инициализировать переменные, объявленные в глобальном пространстве и переменные, объявленные внутри функции, а вот переменные-члены класса нельзя проинициализировать прямо там же внутри описания класса.

Ты, пожалуйста, всегда добавляй - "в шестёрке". А то звучит странно для современного плюсовика.
Цитата:
Дядя Миша писал:
Потому что никакой реальной инициализации в этом месте всё равно не происходит.

В каком "в этом" месте?
Цитата:
Дядя Миша писал:
бедные программисты, которые очень бояться перетрудится и написать несколько лишних букв в массе своей стараются не писать это слово void

Они не пишут его потому, что оно избыточно, и зашумляет текст.
Ты небось тоже не пишешь для каждого объявления инта - signed int.
Цитата:
Дядя Миша писал:
Нет, если серъезно, мне кажется что так красивее выглядит, поэтому и писал.

Ну это красота уровня public static final void.
Цитата:
Дядя Миша писал:
Это вам не Раст, который анализирует исходник целиком.

Это как?
Цитата:
Дядя Миша писал:
int foo( 5 ); // direct member initialization

А вот так у тебя можно?
C++ Source Code:
class CObject {
  int i = foo(5);  // function call
};

__________________

xaerox on Vivino


Отправлено Дядя Миша 07-08-2024 в 07:02:

Цитата:
XaeroX писал:
Ты, пожалуйста, всегда добавляй - "в шестёрке". А то звучит странно для современного плюсовика.

До 11-й версии, если быть точным.

Цитата:
XaeroX писал:
В каком "в этом" месте?

В месте объявления.

Цитата:
XaeroX писал:
Они не пишут его потому, что оно избыточно, и зашумляет текст.

Глупазте. Четыре буквы текст зашумить не могут. Текст зашумляют бесконечные обращения к STL, вызов лямбд и прочая аналогичная пакость, которой болеет современный С++.

Цитата:
XaeroX писал:
Это как?

А хрен его знает. Он же сперва парсит сорцы, а потом минут 20 думает о вечном.

Цитата:
XaeroX писал:
А вот так у тебя можно?

А что такое foo в данном контексте?

Добавлено 07-08-2024 в 10:02:

Добавил также инициализацию через = поскольку это поддерживается при инициализации объектов на стеке и в куче, следовательно логично поддержать это и здесь.
C++ Source Code:
1
class CObject
2
{
3
  vec3	origin( 10.0f, 20.0f, 30.0f );	// direct member initialization
4
  vec3	angles( 30.0f, 20.0f, 10.0f );	// direct member initialization
5
  vec3	scale = 1;				// initialization by default
6
 
7
  vec3	pool[10] = 0;
8
  vec3	test[10]( 0.0f, 1.0f, 0.0f );
9
public:
10
  int	foo = 5;				// direct member initialization
11
};

Но обратите внимание, конструкция вот такого вида
C++ Source Code:
vec3	scale = vec3( 1 );

не поддерживается, т.к. это не константное выражение. Члены класса можно инициализировать только константами.
В дальнейшем надо будет так же сделать инициализацию ссылок членов класса, поскольку они фактически были невозможными в старых версиях С++. Но я так и не смог придумать для чего подобное может понадобиться. Разве что представить ссылку в виде константного свойства только для чтения. Но в Шоте есть полноценные свойства. Так что пока не горит. Но для консистентности, разумеется надо будет потом сделать.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 08-08-2024 в 02:48:

Цитата:
Дядя Миша писал:
Текст зашумляют бесконечные обращения к STL, вызов лямбд и прочая аналогичная пакость, которой болеет современный С++.

Ну вообще идея STL-алгоритмов как раз повысить читабельность. Вместо цикла - понятное название, скажем std::find_if.
Цитата:
Дядя Миша писал:
А что такое foo в данном контексте?

Ну скажем, глобальная функция. В плюсах можно написать вот так:
C++ Source Code:
1
int foo(int i) {
2
  return sqrt(i);
3
}
4
 
5
struct C {
6
  int i = foo(25);
7
};

И вот так можно написать - для эстетов:
C++ Source Code:
1
int foo(int i) {
2
  return sqrt(i);
3
}
4
 
5
struct C {
6
  int i = [](){ return foo(25); }();
7
};

А можно и вот так!
C++ Source Code:
1
int foo(int i) {
2
  return sqrt(i);
3
}
4
 
5
struct C {
6
  int i = 2*[](){ return foo(25); }();
7
};

Понятно, что вместо явно прописанных цифровых констант могут быть конст-переменные или макросы.
А могут быть другие функции. Вообще любые функции, они будут выполняться в момент создания экземпляра класса.

__________________

xaerox on Vivino


Отправлено Дядя Миша 08-08-2024 в 06:01:

Цитата:
XaeroX писал:
скажем std::find_if.

Вот эти std:: зашумляют текст куда сильнее чем void. Как раз из-за двоеточий.

Цитата:
XaeroX писал:
Ну скажем, глобальная функция.

Так скажем, или глобальная? Я такого не делал, только инициализацию константными значениями. Но если мне такое понадобится, можно будет подумать.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено XaeroX 08-08-2024 в 12:44:

Цитата:
Дядя Миша писал:
Но если мне такое понадобится, можно будет подумать.

Ну а если остальным такое понадобится, они просто возьмут С++. Логично.

__________________

xaerox on Vivino


Отправлено Дядя Миша 08-08-2024 в 13:14:

Цитата:
XaeroX писал:
Ну а если остальным такое понадобится, они просто возьмут С++. Логично.

В шестёрке так допустим было нельзя, но все работали в ней и никто не жужжжал!

Впрочем, учитывая архитектуру Шота, я могу ещё много интересных конструкций добавить в язык, чисто в рамках компилятора. Интерпретатор останется прежним и совместимость тоже не пострадает.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 30-08-2024 в 12:19:

Кстати. Порядок инициализации глобальных конструкторов в cinit определён порядком исходных файлов, подаваемых на вход компиляции.
А порядок исходных файлов в свою очередь нарушен быть не может, т.к. компилятор автоматически сортирует их по алфавиту. Таким образом, если вы делаете какой-то надкласс, который призван следить за всеми остальными, ну например отладчик памяти, файл с объявлением экземпляра должен называться таким образом, чтобы гарантировано стать первым в списке компиляции. Ну например с восклицательного знака.
Но в шестёрке есть баг, что если добавить файл и сразу же начать компиляцию, то он будет добавлен в список самым последним.
Помогает выгрузка - загрузка проекта. Но возможно что этот баг так до сих пор не исправили и в новых студиях.
В Шоте авто-сортировки по именам нету, можно вручную задавать приоритеты. Но да, принцип тот же.
Кстати этот момент технично обходится во всех учебниках по С++ и возможно вообще не подлежит стандартизации.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 10-09-2024 в 15:22:

Добавил новый compile-time оператор is_polymorphic. Это аналог std::is_polymorphic, позволяет получить ответ, есть ли в классе виртуальные методы. Пригодится.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 12-09-2024 в 10:08:

Интересное дело. НИГДЕ не удалось нагуглить даже малейших следов описания приоритета неявного приведения операторов преобразования типов. Эта тема, то ли считается неважной, то ли про нее тоже никто не знает. Приведу пример:

C++ Source Code:
1
class CVarFloat
2
{
3
  float	value;
4
public:
5
  CVarFloat() : value(0.0f) {}
6
  CVarFloat( float in ) : value(in) {}
7
  operator float() const { return value; }
8
};

Вот у нас есть такой симпатичный прокси-класс. И поскольку у него есть оператор приведения типа к float мы естественно хотим его умножить.
C++ Source Code:
1
CVarFloat	a( 2.0f );
2
CVarFloat	b( 2.0f );
3
 
4
float fc = a * b;
5
int ic = a * b;
6
bool bc = a * b;
7
Msg( "%g %d %d\n", fc, ic, bc );

Это нам выдаст 4 4 1. Почему в случае с bool получился 1 нас сейчас не особо интерисует, т.к. это всё равно невалидная операция. Явно не то, чтобы мы хотели получить. Интересно другое. Каким образом компилятор дотумкал во что ему надо преобразовывать типы? Но мы пойдем дальше.
Добавим явное преобразование в int. Вот так
C++ Source Code:
1
class CVarFloat
2
{
3
  float	value;
4
public:
5
  CVarFloat() : value(0.0f) {}
6
  CVarFloat( float in ) : value(in) {}
7
  operator float() const { return value; }
8
  operator int() const { return value; }
9
};

В результате получим три ошибки
C++ Source Code:
error C2593: 'operator *' is ambiguous

Но почему, собственно? Он теперь не может выбрать какой использовать? Значит на тип операнда в который пишется результат он не смотрит. Хорошо. Но и на тип второго операнда он смотреть не может. Это бы имело значение, если бы A был float или B был float. Однако у нас тут два класса, которые потенциально можно привести к какому-то простому типу.
Очевидно, раз компилятор НЕ МОЖЕТ полагаться на типы ABC, он выполняет приведение соответствуясь с некоторыми внутренними жестко установленными правилами. Ну а как ещё-то? То есть скажем в первую очередь пытается привести ко float, затем к int. Ну это навскидку. Я этих правил не знаю. И НАГУГЛИТЬ ИХ НИГДЕ НЕ УДАЛОСЬ АБСОЛЮТНО.
Никто про это даже не вспоминает. А возможно и не знает даже или просто не задумывается как работает эта магия.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Unit 12-09-2024 в 16:05:

Цитата:
Дядя Миша писал:
Но почему, собственно? Он теперь не может выбрать какой использовать?


When two or more user-defined conversions that perform the same conversion are available at a conversion site, the conversion is said to be ambiguous. Such ambiguities are an error because the compiler can't determine which one of the available conversions it should choose

Моё мнение - весь этот сахар с операторами преобразования приводит к ошибкам, которые даже заметить порой сложно.
Лучше использовать каст методы с "говорящими" именами, toString(), toFloat() и т.д.


Отправлено Дядя Миша 12-09-2024 в 21:01:

Ну я уже понял, что для выражения C = A x B где x арифметическое действие, нет никакой возможности выбрать правильный тип для преобразования. C может отсутствовать вообще, если выражение передается аргументом в функцию, финальный тип которого в свою очередь учитывает дедуктор перегрузки функций. Так что видимо да - только выбор из одного оператора. Сделал аналогично.

Добавлено 13-09-2024 в 00:01:

При этом разумеется кол-во операторов приведения типов по-прежнему может быть каким угодно, но в спорных случаях требуется явный каст.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено PRoSToTeM@ 12-09-2024 в 22:07:

Цитата:
Дядя Миша писал:
Интересное дело. НИГДЕ не удалось нагуглить даже малейших следов описания приоритета неявного приведения операторов преобразования типов. Эта тема, то ли считается неважной, то ли про нее тоже никто не знает.

https://en.cppreference.com/w/cpp/l...icit_conversion

Цитата:
Дядя Миша писал:
Приведу пример:

C++ Source Code:
1
class CVarFloat
2
{
3
  float	value;
4
public:
5
  CVarFloat() : value(0.0f) {}
6
  CVarFloat( float in ) : value(in) {}
7
  operator float() const { return value; }
8
};

Вот у нас есть такой симпатичный прокси-класс.

Добавим пару функций:
C++ Source Code:
1
auto bar(float lhs, float rhs) {
2
  return lhs * rhs;
3
}
4
 
5
auto bar(int lhs, int rhs) {
6
  return lhs * rhs;
7
}

В данном случае в следующих двух выражениях выполняется одна и та же логика с implicit casts:
C++ Source Code:
a * b // calls operator*(float, float)
bar(a, b) // calls bar(float, float)

Соответственно, если добавить в класс operator int, то будет ambiguous в обоих случаях. Т.е. использование операторов ничем не отличается от вызова функций (во многих ситуациях).

Можно потыкаться на compiler-explorer.


Отправлено Дядя Миша 18-09-2024 в 07:15:

Большое дело сделал - отложенную кодогенерацию шаблонных методов.
Теперь если какие-то функции из шаблонного класса используют операторы\методы, которых нет в классе, представленном в качестве шаблонного аргумента, то компилятор на это не ругается при условии, что эти функции нигде в коде не были вызваны, ну потому что код генерируется только для реально использованных функций.

Вот простой пример: в шаблонном классе динамического контейнера есть метод find, который сравнивает объект из своего аргумента с объектами, находящимися в массиве через оператор ==. Если шаблон сразу же инстанцирует все свои функции, то от каждого такого класса он будет требовать наличие пользовательского оператора ==. Это весьма неудобно, если учесть что пользователь сам метод find может и вовсе не вызывать.
Теперь этой проблемы нет. Ну а сам принцип хранения исходного кода в структуре объявленных функций наталкивает меня на мысль, что вместо того чтобы явным образом эмитить опкоды (как я это делаю сейчас для тех функций, которые генерирует компилятор) можно просто генерировать исходный текст этих функций. Это ведь намного проще и удобнее - думать не надо средствами компилятора. А компилятор их потом сам распарсит, как будто бы это настоящие функции. Весьма вероятно что всякие копи-конструкторы, которые генерирует компилятор, я именно так и реализую - генерацией исходного кода, а не серией вызовов EmitAddress, EmitObjectCall и прочего.

Добавлено 18-09-2024 в 10:15:

Тут ещё положительный момент в том, что компилятор будет как бы контролировать сам себя в момент парсинга этих функций. Ведь если я ошибусь, он сразу выдаст ошибку.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Дядя Миша 30-10-2024 в 09:38:

Объявил элемент двухсвязного списка, а его же по дефолту надо инициализировать самим собой, ну я и написал:

C++ Source Code:
1
struct link_t
2
{
3
  link_t	*next;
4
  link_t	*prev;
5
 
6
  link_t() : next(this), prev(this) {}
7
};

И моментально получил варнинг
warning C4355: 'this' : used in base member initializer list

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 30-10-2024 в 11:22:

Цитата:
Предупреждение C4355: 'this' : used in base member initializer list возникает потому, что вы используете указатель this в списке инициализации членов до того, как объект полностью создан. Это может привести к неопределенному поведению, так как объект еще не находится в корректном состоянии.

В вашем случае, если вы хотите инициализировать элемент двусвязного списка самим собой, вам нужно сделать это после того, как объект будет полностью создан. Вы можете использовать конструктор по умолчанию для инициализации указателей next и prev в nullptr, а затем в теле конструктора установить их на this.


C++ Source Code:
1
struct link_t
2
{
3
  link_t* next;
4
  link_t* prev;
5
 
6
  link_t() : next(nullptr), prev(nullptr)
7
  {
8
    next = this;
9
    prev = this;
10
  }
11
};

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Дядя Миша 03-01-2025 в 15:20:

На редкость запутанная хрень даже в варианте с двумя терминами

https://habr.com/ru/articles/348198/

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Crystallize 03-01-2025 в 17:11:

Дядя Миша короче сишный вариант локусов из спирита


Отправлено Дядя Миша 04-01-2025 в 06:29:

Crystallize вообще не в тему.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено FiEctro 06-01-2025 в 23:52:

А как там эти локусы работали?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено Crystallize 07-01-2025 в 07:45:

FiEctro они в зависимости от контекста старались быть всем чем угодно, причем в каждой энтите по-своему.


Отправлено Дядя Миша 08-01-2025 в 10:41:

Locus это как this. Что тут запутанного?

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Отправлено Crystallize 09-01-2025 в 02:13:

Дядя Миша Это оно так начинается, за здравие. Потом вырастает в неподъёмную кучу фичей. Там половина фунеционала-кто активировал энтитю, и половина-кого активировать энтитей. И всё свалено вместе.
https://ralertmod.narod.ru/sohl-articles-locuscalc.htm


Отправлено Дядя Миша 09-01-2025 в 15:19:

Crystallize так ты локусы с кальками не путай, разные ведь вещи.
Вторые как раз были призваны компенсировать ограничения парент-системы.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Временная зона GMT. Текущее время 06:10.
Показать все 188 сообщений этой темы на одной странице

На основе vBulletin версии 2.3.0
Авторское право © Jelsoft Enterprises Limited 2000 - 2002.
Дизайн и программирование: Crystice Softworks © 2005 - 2024