Войти
ПрограммированиеФорумОбщее

Типизированные int'ы (8 стр)

Страницы: 14 5 6 7 8 9 Следующая »
#105
10:51, 16 июля 2019

Типизированные инты для индексов это годная идея. Я так в расте сделал пул объектов https://github.com/mrDIMAS/rg3d/blob/master/src/utils/pool.rs - только там еще к индексу прилеплен номер поколения объекта, чтобы была возможность проверять что индекс (хендл) указывает на тот же объект для которого был создан.

#106
10:52, 16 июля 2019

2019 год, очередную тонну сахара в крестостандарт завезли, IDE с всплывающими комментариями не завезли. Или просто нынче не модно писать комментарии к методам, типа "хороший код - тот, которому комментарии не нужны". А ведь раньше говорили: "Пишите код так, будто поддерживать его будет вооруженный психопат, который знает где вы живете."

Вот слышал я про рогалик (ни разу не играл, название забыл) где персонаж в процессе отращивает дополнительные части тела, и решил написать своего игоря с подобной механикой. Допустим хочу специфический квест, в котором персонаж для его завершения должен отрастить дополнительные ноги и чтоб их общее число было не меньше уровня персонажа, челлендж для игрока в том, что большое количество уже только мешает передвигаться, в процессе приобретения ног возможен левелап ("Больше ног богу ног! Больше вонючих носков для Трона Вонючих Носков!"), избавление от лишних ног после квеста может быть дорогим и/или болезненным, и т.п.
И в итоге получится: сначала нужно сожрать один кактус чтоб эту супертипизацию написать, а потом еще один кактус - расставляя повсюду касты, компенсирующие супертипизацию.

На днях читал код библиотеки OpenEXR, там такую же хрень замутили с некоторыми полями заголовка файла. На фига оно надо реально, если базовые типы данных (строка, uint, short, char, float, half-float) и так определены в стандарте, равно как и фактические значения всех перечислений - ну вот чисто шаблонами подро... в посыпании сахаром поупражняться.

#107
10:58, 16 июля 2019

StepEver
> Когда передаём в функцию 2 индекса, для двух разных коллекций, где объект
> одной, к примеру, что-то делает с объектом другой. Легко на входе перепутать
> индексы.
Я говорю, это всё из пальца высосано. Откуда эти индексы придут? Объекты всё равно будут искаться через позицию мыши, или через меню, где никакой этой типизации не будет. Или в цикле принятия решений, где эту ошибку легко отловить без типизации. А типизация потащит за собой обслуживающие функции, необходимость каста и пространство для ещё больших ошибок.

"Один объект что-то делает с другим" это полный бред в реалиях любого проекта. Это пример из какого-то скрипта для кастомной карты, сделанной мододелом. И там это проще решить строковыми идентификаторами, никто не будет там искать по численному ID и записывать его.

Весь сет делает что-то с другим сетом.

StepEver
> Ну или ещё пример, у меня ПДУ от телевизора с двумя одинаковыми кнопками для
> переключения каналов и для регулировки звука.
Нет никакого единого закона существования всех вещей, чтобы приводить метафору с пультом. Пульт:
а) используется в 1000 раз чаще, чем любая эта функция будет написана, проблематичность ошибки на пульте несравнимо выше
б) тяжело кастомизируется
Мы говорим про реальное железо, у которого есть определённые условности (покадровая отрисовка, внешний ввод, который не оперирует условностями ЯП), а не про гномиков в системном блоке, которые друг друга используют по ID.

#108
11:07, 16 июля 2019

NyakNyakProduction
> Я говорю, это всё из пальца высосано. Откуда эти индексы придут?
SetRect(RECT*, int, int, int, int); - кто последние два параметра? cx, cy или r, b?

> А типизация потащит за собой обслуживающие функции, необходимость каста и пространство для ещё больших ошибок.
Функции будут те же, но с другими параметрами. Сам индекс - простой класс. Каст тоже простой, можно сделать на уровне класса-индекса. Зато типизация будет отлавливать ошибки на компиляции, что на порядок удобнее.

> Мы говорим про реальное железо, у которого есть определённые условности (покадровая отрисовка, внешний ввод, который не оперирует условностями ЯП)
я сурово уверен, что мой класс-индекс в релиз-сборке в асме ничем не будет отличаться от обычного int-а.

#109
11:11, 16 июля 2019

StepEver
> SetRect(RECT*, int, int, int, int);
А где так написано? Разве в хедере не должно быть

SetRect(RECT * pRect, int x0, int y0, int x1, int y1);
#110
11:14, 16 июля 2019

NyakNyakProduction
> "Один объект что-то делает с другим" это полный бред в реалиях любого проекта. Это пример из какого-то скрипта для кастомной карты, сделанной мододелом. И там это проще решить строковыми идентификаторами, никто не будет там искать по численному ID и записывать его.
Кстати, вспомнил, это реальный пример из проекта, который я сейчас переписываю на жёсткую типизацию. До этого он был на нодах. Примеров там куча, навскидку, атака одного корабля другим, функция, два параметра - указатели на ноды. Мало того, что можно порядок перепутать, можно ещё и не те ноды подсунуть. Другой пример, переключение между сценами, функция, три параметра, номер сцены и две ноды - два объекта, в одном случае, это планета(вторая нода игнорируется), в другом случае, это два флота. Вроде как не страшно, но сама иерархия нод такова, что можно где-то забыть пройтись в нужный узел и передать не ту ноду, что бывало.

#111
11:15, 16 июля 2019

Ranma
> А где так написано? Разве в хедере не должно быть
В хедере, возможно, но не все IDE подсвечивают названия параметров.

#112
(Правка: 11:30) 11:28, 16 июля 2019

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

struct Graph
{
  struct Node
  {
    glm::vec4 color;
  };
  std::vector<Node> nodes;
  struct Edge
  {
    size_t nodeIndices[2];
  };
  std::vector<Edge> edges;
};
суть в том, что вот такой код вообще не должен компилироваться:
  auto &edge = edges.back();
  size_t index = edge.nodeIndices[0];
  DoSomething(edges[index]);
потому что здесь index — это индекс ноды, поэтому некорректно обращаться по этому индексу к массиву рёбер. этого легко можно было бы избежать, если бы векторы поддерживали обращение по типизированным индексам. Проблема с индексами часто встречается именно в реализациях низкоуровневых структур данных вроде пулов, графов, списков, деревьев итп, где обращаться к элементам часто нужно именно по индексам и типичной ситуацией является несколько уровней индирекции вида somethings[indices[balbla.elements[ i ]]].

Ranma
> И в итоге получится: сначала нужно сожрать один кактус чтоб эту супертипизацию
> написать, а потом еще один кактус - расставляя повсюду касты, компенсирующие
> супертипизацию.
лол, то есть с идеей использования типизированных указателей у вас проблем нету, а от остальных типизированных элементарных типов сразу разрывает шаблон и интеллект отключается. указатели ведь вы тоже не приводите друг к другу без острой необходимости? потому что они не просто так сделаны несовместимыми на уровне языка. и несмотря на то, что иногда при написании экзотики вроде менеджера памяти нужно вручную указатели кастить, в 99% обычного кода, неявные касты указателей бы приводили к ошибкам.

> OpenEXR
> базовые типы данных (строка, uint, short, char, float, half-float)
я без понятия, какое это вообще имеет отношение к теме, но вообще-то точный размер этих типов нигде не стандартизован и поэтому для бинарной сериализации их никто не использует. для сериализации используются типы фиксированного размера вроде uint8_t.

#113
11:40, 16 июля 2019

StepEver
> В данном примере - одну.
Это неконструктивно, бро. Очевидно, что таких примеров - сотни в нормальном проекте. Значит и перегружать придется сотни.

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

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

> Ну и ещё раз напоминаю: типизированные int-ы, это просто ещё одна возможность,
> а не обязательность.
То есть эта фича только для очень узких границ применения, поэтому, она и отловит 1 из 1000 подобных ошибок (ведь везде кроме индексов будут голые инты), а, значит, вводить такие вещи на уровень языка или хотя бы на уровень стиля кодирования отдельного проекта - ошибочно.

#114
11:42, 16 июля 2019

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

#115
(Правка: 11:50) 11:48, 16 июля 2019

кстати, всем иннуэндам и компании, которые никогда в жизни не сталкивались с проблемами несовместимых интов: https://github.com/KhronosGroup/SPIRV-Cross/blob/master/spirv_cross.hpp

в этой библиотеке, например, вообще все id'шники для вообще всего — это просто uint'ы. то есть вот такой код:

Resource buffer = compiler.get_shader_resources()... ///
uint32_t setId = compiler.get_decoration(buffer.type_id, spv::DecorationDescriptorSet);
прекрасно скомпилится. а может, надо было так?
uint32_t setId = compiler.get_decoration(buffer.base_type_id, spv::DecorationDescriptorSet);
или так?
uint32_t setId = compiler.get_decoration(buffer.id, spv::DecorationDescriptorSet);
а вот тут?
compiler.get_member_name(buffer.base_type_id, memberIndex);
и такое сплошь и рядом во всех API, которые не парятся по поводу такой ерунды как юзабилити.

#116
11:54, 16 июля 2019

StepEver
Если не подсвечивает - можно ведь и посмотреть определение/документацию, а не ждать, что компилятор все сам будет делать. Или синтаксическую проверку тоже компилятору поручаете?

Suslik
> с идеей использования типизированных указателей у вас проблем нету
Мне они тоже не нравятся (лол), но совсем без них не обойтись.

> точный размер этих типов нигде не стандартизован
В документации OpenEXR они описаны, в коде используются простые сишные определения типа "unsigned short" вместо "uint16_t".

#117
11:55, 16 июля 2019

Мы опять разбежались. Есть проблема абстрактных индексов (которая успешно решается или указателями, или итераторами, или абстрактными хэндлами), а есть "полезная фича" размерных интов, которая совсем не полезна, потому что никто не предложил хорошей её реализации даже вне рамок стандартного языка.

#118
11:58, 16 июля 2019

Suslik
Прекрасно, осталось толковую документацию прикрутить :-D

#119
(Правка: 12:04) 12:02, 16 июля 2019

Went
> Есть проблема абстрактных индексов (которая успешно решается
никак она не решается

> или указателями
указатели не инвариантны при переаллокации. поэтому код вроде #112 работать не будет на указателях, равно как не будет работать код на архитектуре без указателей вроде шейдеров.

> или итераторами
итераторы хранят указатель на контейнер, что автоматически делает их непригодными для любого time-critical кода и не являются достаточно общим решением, так как решают только проблему индексации.

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

> "полезная фича" размерных интов, которая совсем не полезна, потому что никто не предложил хорошей её реализации даже вне рамок стандартного языка.
это не отдельная фича, это применение той же самой фичи в другой области. как бы о том и обсуждение, что полноценно это реализовать без strong typedef'ов нельзя, можно только костылить. в этом и отстой. иначе ты бы сейчас не на форуме сидел, а на каком-нибудь хабре читал статью про то, какие классные в C++ добавили strong typedef'ы и не понятно, как до этого вообще без них жили.

Страницы: 14 5 6 7 8 9 Следующая »
ПрограммированиеФорумОбщее