Как правильно объявить структуру?

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Re: Как правильно объявить структуру?

Сообщение Alek_Aaz » 30.08.2019 06:01:36

iskander писал(а):Но имхо "шустро" с использованием Variant не будет.

Да, верно. Тестил тут. Если использовать в нескольких операциях +-* variant вместо double, производительность падает где-то 5-6 раз(возможно будет и больше). Если на входе в процедуру присваивать локальным простым переменным(double) данные из варианта, выполнять операции, и на выходе присваивать варианту получившиеся значения производительность падает "только" :D в 2 раза.
Пока не вышел релиз 3.2 буду делать через варианты, оптимизация - потом. Главное концепцию отработать. :roll:

iskander писал(а):Если непременно нужно, чтобы Data: Variant торчал наружу, то может быть так?

Ну почему "неприменно". Просто это универсальный вариант.

Вообще общая картина видится как-то так:
Код: Выделить всё
  TECSElement = record
    Name: string;
    Data: Variant;       // ?????
  end;

  TECSComponent = class
...
    Name: string;
    Elements: array of TECSElement;       
....
  end;

  TECSEntity = class
...
    Name: string;
    Component: array of TECSComponent;       
....
  end;

  TECSEntityArray = class
...
    Name: string;
    Entity: array of  TECSEntity;       
....
  end;

Var
          MyWorld:TECSEntityArray;


Ну и как-бы выражение
Код: Выделить всё
MyWorld.Entity[i].ComponentByName('speed').ElementByName('actualspeed').data:=MyWorld.Entity[i].ComponentByName('speed').ElementByName('actualspeed').data+MyWorld.Entity[i].ComponentByName('speed').ElementByName('acceleration').data ;

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

Есть еще один вариант универсальной записи. Data:WideString. Возможно преобразование string->int64,Currency,array будет работать шустрее чем варианты.
У, еще нужно тип bool поддерживать, но это не важно походу.

Добавлено спустя 23 минуты 22 секунды:
iskander писал(а):Если непременно нужно, чтобы Data: Variant торчал наружу, то может быть так?


А такой вариант не работает на 3.2 ???
Код: Выделить всё
class operator TECSElement.:=(const aValue: array of byte): TECSElement;
begin
  Result.dataType:=ecsArray;
  DynArrayToVariant(Result.data,Pointer(aValue),TypeInfo(aValue));
end;


Добавлено спустя 5 минут 1 секунду:
Может конечно и не пихать массивы в структуру, раз с ними такие заморочки, но просто WideString суть есть тот же массив, а длинные строки нужны однозначно.
Alek_Aaz
новенький
 
Сообщения: 40
Зарегистрирован: 26.11.2007 04:13:06

Re: Как правильно объявить структуру?

Сообщение iskander » 30.08.2019 10:53:06

runewalsh, случай, когда структура умещается в регистре(или в двух) "очевидно уместным" не является. А насчет "лишней когнитивной нагрузки" - вы это серьезно?

Alek_Aaz, Variant, спрятанный в private секции, обеспечивает(с помощью перегруженных операторов) полный контроль времени компиляции набора типов, которые он может принимать. Поле DataType лишнее, оно дублирует поле VType варианта и к тому же требует инициализации.
Должно компилироваться(и, возможно, даже работать :)) в 3.0.4:
Код: Выделить всё
unit ECSElement;

{$mode objfpc}{$H+}
{$modeswitch advancedrecords}

interface

uses
   SysUtils, Variants;

type
  TECSDataType = (ecsEmpty, ecsInt64, escCurrency, ecsWideString, ecsArray);

  TECSData = record
  private
    FData: Variant;
  public
    class operator := (aValue: Int64): TECSData;
    class operator := (aValue: Currency): TECSData;
    class operator := (const aValue: widestring): TECSData;
    class operator := (const aValue: TBytes): TECSData;
    class operator := (const aData: TECSData): Int64;
    class operator := (const aData: TECSData): Currency;
    class operator := (const aData: TECSData): widestring;
    class operator := (const aData: TECSData): TBytes;
  end;

  TECSElement = record
    Name: string;
    Data: TECSData;
    function DataType: TECSDataType;
  end;

implementation

{ TECSElement }

function TECSElement.DataType: TECSDataType;
begin
  case VarType(Data.FData) of
    VarInt64:    Result := ecsInt64;
    VarCurrency: Result := escCurrency;
    VarOleStr:   Result := ecsWideString;
  else
    if VarIsArray(Data.FData) then
      exit(ecsArray);
    Result := ecsEmpty;
  end;
end;

{ TECSData }

class operator TECSData.:=(aValue: Int64): TECSData;
begin
  Result.FData := aValue;
end;

class operator TECSData.:=(aValue: Currency): TECSData;
begin
  Result.FData := aValue;
end;

class operator TECSData.:=(const aValue: widestring): TECSData;
begin
  Result.FData := aValue;
end;

class operator TECSData.:=(const aValue: TBytes): TECSData;
begin
  DynArrayToVariant(Result.FData, Pointer(aValue), TypeInfo(aValue));
end;

class operator TECSData.:=(const aData: TECSData): Int64;
begin
  // здесь можно проверить несовпадение типов
  // иначе возможно получить неявное приведение типов
  // или невнятное исключение типа EVariantTypeCastError

  Result := aData.FData;
end;

class operator TECSData.:=(const aData: TECSData): Currency;
begin
  //здесь можно проверить несовпадение типов;

  Result := aData.FData;
end;

class operator TECSData.:=(const aData: TECSData): widestring;
begin
  //здесь можно проверить несовпадение типов

  Result := aData.FData;
end;

class operator TECSData.:=(const aData: TECSData): TBytes;
begin
  //здесь можно проверить несовпадение типов

  DynArrayFromVariant(Pointer(Result), aData.FData, TypeInfo(Result));
end;

end.
iskander
энтузиаст
 
Сообщения: 606
Зарегистрирован: 08.01.2012 18:43:34

Re: Как правильно объявить структуру?

Сообщение runewalsh » 30.08.2019 13:10:29

iskander писал(а):случай, когда структура умещается в регистре(или в двух) "очевидно уместным" не является

Так это от платформы зависит, будет умещаться или нет, поэтому такие вещи нужно доверить компилятору. С точки зрения чистого Pascal-кода const и constref работают абсолютно идентично, ты не сможешь без хаков что-то записать в место, куда ссылается указатель за constref-переменной (и эта операция бессмысленна, потому что он может указывать на временный объект типа пятёрки в предыдущем примере), поэтому неважно, как она передана под капотом.
iskander писал(а):А насчет "лишней когнитивной нагрузки" - вы это серьезно?

Я просто не понял довода про использование потенциально неоптимального constref вместо const, поэтому попробовал довести до абсурда, дескать, почему бы в таком случае не использовать потенциально неоптимальную передачу по значению вместо const.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Как правильно объявить структуру?

Сообщение iskander » 30.08.2019 13:26:28

Ну хорошо, убедили :) .
iskander
энтузиаст
 
Сообщения: 606
Зарегистрирован: 08.01.2012 18:43:34

Пред.

Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

Рейтинг@Mail.ru