powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Generics Variant to Type
25 сообщений из 27, страница 1 из 2
Generics Variant to Type
    #39396445
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такой код
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
class procedure TCustomResultReader.VarToArray(const AVal: Variant;
  out AResult: TArray<Smallint>); overload;
var
  LLen: Integer;
  Li: Integer;
begin
  LLen := VarArrayHighBound(AVal, 1) - VarArrayLowBound(AVal, 1) + 1;
  SetLength(AResult, LLen);
  if LLen = 0 then
    Exit;
  if (VarType(AVal.Val) and varTypeMask) in [varSmallint, varWord] then
    CopyVarArray(AVal, @AResult[0])
  else begin
    for Li := 0 to LLen - 1 do
      AResult[Li] := AVal[Li];
  end;
end;

class procedure TCustomResultReader.VarToArray(const AVal: Variant;
  out AResult: TArray<Integer>); overload;
var
  LLen: Integer;
  Li: Integer;
begin
  LLen := VarArrayHighBound(AVal, 1) - VarArrayLowBound(AVal, 1) + 1;
  SetLength(AResult, LLen);
  if LLen = 0 then
    Exit;
  if (VarType(AVal.Val) and varTypeMask) in [varInteger, varLongWord] then
    CopyVarArray(AVal, @AResult[0])
  else begin
    for Li := 0 to LLen - 1 do
      AResult[Li] := AVal[Li];
  end;
end;

class procedure TCustomResultReader.VarToArray(const AVal: Variant;
  out AResult: TArray<Double>); overload;
begin
  .......
end;


Вопрос - можно ли эти процедуры сгруппировать в одну?
Если пишу как-то так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
class procedure TCustomResultReader.VarToArray<T>(const AVal: Variant;
  const AValidMask: set of TVarType; out AResult: TArray<T>); 
var
  LLen: Integer;
  Li: Integer;
begin
  LLen := VarArrayHighBound(AVal, 1) - VarArrayLowBound(AVal, 1) + 1;
  SetLength(AResult, LLen);
  if LLen = 0 then
    Exit;
  if (VarType(AVal.Val) and varTypeMask) in AValidMask then
    CopyVarArray(AVal, @AResult[0])
  else begin
    for Li := 0 to LLen - 1 do
      AResult[Li] := AVal[Li];
  end;
end;

то на выделенной строке возникает ошибка
E2010 Incompatible types: 'T' and 'Variant'ошибка, как-бы логичная.

С уважением, Vasilisk
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396451
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Копируй память.
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396458
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatКопируй память.Память я копирую если типы совпали. А если нет, то мне еще нужна конвертация Variant
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396461
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
case PTypeInfo(TypeInfo(TValue)).Kind of
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396463
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В твоем случае
case PTypeInfo(TypeInfo(T)).Kind of
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396474
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatcase PTypeInfo(TypeInfo(T)).Kind ofИ что мне это даст? У меня будет tkInteger или tkFloat. Все равно мне нужна конвертация варианта в конкретный тип.

Скажем T: SmallInt, VarType(AVal[0]) = varDouble

И, что куда копировать?
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396480
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Скажем T: SmallInt, VarType(AVal[0]) = varDouble
И, что куда копировать?
А что ты вообще хотел в таком случае?
Оно конечно можно попробовать взять Round(AVal[0]), но я бы Raise сделал. :)
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396485
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatА что ты вообще хотел в таком случае?Я бы хотел вызвать стандартный метод конвертирования варианта
Код: pascal
1.
2.
3.
4.
5.
6.
7.
function _VarToInteger(const V: TVarData): Integer;
function _VarToInt64(const V: TVarData): Int64;
function _VarToUInt64(const V: TVarData): UInt64;
function _VarToBool(const V: TVarData): LongBool;
function _VarToReal(const V: TVarData): Extended;
function _VarToCurrency(const V: TVarData): Currency;
...........

...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396489
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Замени строку присваивания на инлайновую процедуру копирования:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Type

 TRec = Record

  Class Procedure CopyToVar<T>(Const AValue : T; Var AResult : Variant); Static; Inline;

 End;

//
Class Procedure TRec.CopyToVar<T>(Const AValue : T; Var AResult : Variant);
Begin

 Case GetTypeKind(T) Of

  tkInteger : AResult := Integer((@AValue)^);
  tkUString : AResult := String((@AValue)^);

 Else

  Error(reAssertionFailed);

 End;

End;
//

var

 r : Variant;

begin

 TRec.CopyToVar('hello', r); // VarFromUStr
 TRec.CopyToVar(1, r); // VarFromInt
 TRec.CopyToVar(3.14, r); // Error

end.


В результате этого кода вместо вызова будет подставлен конкретный кусок кода.
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396494
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Я бы хотел вызвать стандартный метод конвертирования вариантаНичего что double в SmallInt не влезает? :)
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396499
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyЗамени строку присваивания на инлайновую процедуру копирования:О! Спасибо. Думал в этом направлении. Но думал об анонимных коллбеках
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396500
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatНичего что double в SmallInt не влезает? :)127.0 даже в байт влезет :)
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396506
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_О! Спасибо. Думал в этом направлении. Но думал об анонимных коллбеках
Для большей красоты можно взятие адреса заменить на absolute, код получается идентичным:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
//
Class Procedure TRec.CopyToVar<T>(Const AValue : T; Var AResult : Variant);
Var

 IntVal : Integer Absolute AValue;
 StrVal : String Absolute AValue;

Begin

 Case GetTypeKind(T) Of

  tkInteger : AResult := IntVal;//Integer((@AValue)^);
  tkUString : AResult := StrVal;//String((@AValue)^);

 Else

  Error(reAssertionFailed);

 End;

End;
//
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396509
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, вот этот код
Код: pascal
1.
2.
3.
4.
Class Procedure TRec.CopyToVar<T>(Const AValue : T; Var AResult : Variant);
Begin
 Case GetTypeKind(T) Of
  tkInteger : AResult := Integer((@AValue)^);


А вернее вот этот
Код: pascal
1.
2.
3.
4.
Class Procedure TRec.CopyFromVar<T>(Const AValue : Variant; out AResult : T);
Begin
 Case GetTypeKind(T) Of
  tkInteger : Integer((@AResult)^) := AValue;


не подпортит мне соседнюю память при вызове
Код: pascal
1.
2.
3.
4.
5.
var
  LVal: Smallint;
begin
  TRec.CopyFromVar<Smallint>(10, LVal);
end;

?
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396512
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
var
  LVal: record
    Val1, Val2, Val3, Val4: Smallint;
  end;
begin
  TRec.CopyFromVar<Smallint>(10, LVal.Val2);
end;

[/quote]
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396522
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_...не подпортит мне соседнюю память при вызове?
Подпортит. Сделай там дополнительный case по размеру типа.
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396553
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Kazantsev AlexeyЗамени строку присваивания на инлайновую процедуру копирования:О! Спасибо. Думал в этом направлении. Но думал об анонимных коллбеках
У тебя ж 20170086 в другую сторону копирование ?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
set of TVarType; // set of Word ??
// // //

...
  else begin
    for Li := 0 to LLen - 1 do
     case PTypeInfo(TypeInfo(T)).Kind of
      tkInteger : PInteger(@AResult[Li])^ := AVal[Li];
      //...
     end;
  end;
...
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396618
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Наваял такого монстра
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
  TGenericUtils<T> = record
  strict private
    class procedure UnknownType; static;
    class procedure UnsupportedType; static;
  public
    class procedure VarToT(const AVar: Variant; out AOutVal: T); static;
  end;

class procedure TGenericUtils<T>.VarToT(const AVar: Variant; out AOutVal: T);
var
  LByte: Byte absolute AOutVal;
  LWord: Word absolute AOutVal;
  LCrd: Cardinal absolute AOutVal;
  LUInt64: UInt64 absolute AOutVal;
  LShort: ShortInt absolute AOutVal;
  LSmall: SmallInt absolute AOutVal;
  LInt: Integer absolute AOutVal;
  LInt64: Int64 absolute AOutVal;
  LSingle: Single absolute AOutVal;
  LDouble: Double absolute AOutVal;
  LExt: Extended absolute AOutVal;
  LStrS: ShortString absolute AOutVal;
  LStrA: AnsiString absolute AOutVal;
  LStrW: WideString absolute AOutVal;
  LStrU: UnicodeString absolute AOutVal;
  LVar: Variant absolute AOutVal;
begin
  case PTypeInfo(TypeInfo(T))^.Kind of
    tkInteger: begin
      if VarIsUnsigned(AVar) then begin
        case SizeOf(T) of
          SizeOf(LByte): LByte := AVar;
          SizeOf(LWord): LWord := AVar;
          SizeOf(LCrd): LCrd := AVar;
        else
          UnknownType;
        end;
      end else begin  // Is not unsigned
        case SizeOf(T) of
          SizeOf(LShort): LShort := AVar;
          SizeOf(LSmall): LSmall := AVar;
          SizeOf(LInt): LInt := AVar;
        else
          UnknownType;
        end;
      end;
    end;
    tkFloat: begin
      case SizeOf(T) of
        SizeOf(LSingle): LSingle := AVar;
        SizeOf(LDouble): LDouble := AVar;
        SizeOf(LExt): LExt := AVar;
      else
        UnknownType;
      end;
    end;
    tkString: LStrS := AVar;
    tkLString: LStrA := AVar;
    tkWString: LStrW := AVar;
    tkVariant: LVar := AVar;
    tkInt64: begin
      if VarIsUnsigned(AVar) then
        LUInt64 := AVar
      else
        LInt64 := AVar;
    end;
    tkUString: LStrU := AVar;
  else
    UnsupportedType;
  end;
end;

отгреб от компилятора[dcc32 Fatal Error] F2084 Internal Error: AV06152806-R00000000-0сейчас буду шаманить
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396620
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дельфя какая?
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396623
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_[dcc32 Fatal Error] F2084 Internal Error: AV06152806-R00000000-0Минимальный воспроизводимый пример
Код: pascal
1.
2.
3.
4.
5.
6.
class procedure TGenericUtils<T>.VarToT(const AVar: Variant; out AOutVal: T);
var
  LByte: Byte absolute AOutVal;
  LWord: Word absolute AOutVal;
begin
end;
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396624
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatДельфя какая?XE3
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396628
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Угу, на ней лучше не делать сложные генерик рекорды.
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396630
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В Sеattle этот код не глючит.
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396632
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделай вместо TGenericUtils<T> = record -> TGenericUtils<T> = class

Должно заработатью
...
Рейтинг: 0 / 0
Generics Variant to Type
    #39396644
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatСделай вместо TGenericUtils<T> = record -> TGenericUtils<T> = classПробовал.
И так пробовал
Код: pascal
1.
class procedure TGenericUtils.VarToT<T>(const AVar: Variant; out AOutVal: T);

Пофигу. Два абсолюта и приплыли.

Частично решил проблему когда все переменные засунул в вариантный record. Но остались финализируемые типы
...
Рейтинг: 0 / 0
25 сообщений из 27, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Generics Variant to Type
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]