HLFX.Ru Forum Страницы (13): « Первая ... « 7 8 9 10 [11] 12 13 »
Показать все 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)


Отправлено Дядя Миша 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'


Временная зона GMT. Текущее время 03:41. Страницы (13): « Первая ... « 7 8 9 10 [11] 12 13 »
Показать все 188 сообщений этой темы на одной странице

На основе vBulletin версии 2.3.0
Авторское право © Jelsoft Enterprises Limited 2000 - 2002.
Дизайн и программирование: Crystice Softworks © 2005 - 2024