Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Generics Variant to Type / 25 сообщений из 27, страница 1 из 2
01.02.2017, 15:45
    #39396445
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Есть такой код
Код: 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
01.02.2017, 15:49
    #39396451
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Копируй память.
...
Рейтинг: 0 / 0
01.02.2017, 15:53
    #39396458
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
rgreatКопируй память.Память я копирую если типы совпали. А если нет, то мне еще нужна конвертация Variant
...
Рейтинг: 0 / 0
01.02.2017, 15:55
    #39396461
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
case PTypeInfo(TypeInfo(TValue)).Kind of
...
Рейтинг: 0 / 0
01.02.2017, 15:56
    #39396463
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
В твоем случае
case PTypeInfo(TypeInfo(T)).Kind of
...
Рейтинг: 0 / 0
01.02.2017, 16:06
    #39396474
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
rgreatcase PTypeInfo(TypeInfo(T)).Kind ofИ что мне это даст? У меня будет tkInteger или tkFloat. Все равно мне нужна конвертация варианта в конкретный тип.

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

И, что куда копировать?
...
Рейтинг: 0 / 0
01.02.2017, 16:12
    #39396480
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_Vasilisk_Скажем T: SmallInt, VarType(AVal[0]) = varDouble
И, что куда копировать?
А что ты вообще хотел в таком случае?
Оно конечно можно попробовать взять Round(AVal[0]), но я бы Raise сделал. :)
...
Рейтинг: 0 / 0
01.02.2017, 16:21
    #39396485
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
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
01.02.2017, 16:21
    #39396489
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_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
01.02.2017, 16:24
    #39396494
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_Vasilisk_Я бы хотел вызвать стандартный метод конвертирования вариантаНичего что double в SmallInt не влезает? :)
...
Рейтинг: 0 / 0
01.02.2017, 16:27
    #39396499
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Kazantsev AlexeyЗамени строку присваивания на инлайновую процедуру копирования:О! Спасибо. Думал в этом направлении. Но думал об анонимных коллбеках
...
Рейтинг: 0 / 0
01.02.2017, 16:28
    #39396500
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
rgreatНичего что double в SmallInt не влезает? :)127.0 даже в байт влезет :)
...
Рейтинг: 0 / 0
01.02.2017, 16:31
    #39396506
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_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
01.02.2017, 16:34
    #39396509
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Кстати, вот этот код
Код: 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
01.02.2017, 16:37
    #39396512
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Код: 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
01.02.2017, 16:44
    #39396522
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_Vasilisk_...не подпортит мне соседнюю память при вызове?
Подпортит. Сделай там дополнительный case по размеру типа.
...
Рейтинг: 0 / 0
01.02.2017, 17:02
    #39396553
Bred eFeM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_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
01.02.2017, 18:15
    #39396618
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Наваял такого монстра
Код: 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
01.02.2017, 18:16
    #39396620
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Дельфя какая?
...
Рейтинг: 0 / 0
01.02.2017, 18:17
    #39396623
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
_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
01.02.2017, 18:17
    #39396624
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
rgreatДельфя какая?XE3
...
Рейтинг: 0 / 0
01.02.2017, 18:18
    #39396628
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Угу, на ней лучше не делать сложные генерик рекорды.
...
Рейтинг: 0 / 0
01.02.2017, 18:19
    #39396630
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
В Sеattle этот код не глючит.
...
Рейтинг: 0 / 0
01.02.2017, 18:20
    #39396632
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics Variant to Type
Сделай вместо TGenericUtils<T> = record -> TGenericUtils<T> = class

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

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

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


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