HLFX.Ru Forum Страницы (13): « Первая ... « 7 8 9 10 [11] 12 13 »
Показать все 193 сообщений этой темы на одной странице

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(...);

Что абсолютно эквивалетно приведённому выше коду, но не выглядит как объявление функции.


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

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

Ну это, наверное, те же, кто не оставляет комментариев.


Отправлено Дядя Миша 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. Текущее время 15:35. Страницы (13): « Первая ... « 7 8 9 10 [11] 12 13 »
Показать все 193 сообщений этой темы на одной странице

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