关于这个问题的跟进:Conditional behaviour based on concrete type for generic class
我知道您可以使用RTTI检测泛型变量的类型。但是我想更进一步。有没有办法在编译时检测类型。
我有以下代码:
function TBPlusTree<K, V>.TLeaf.AddKey(const Key: K; const Value: V): boolean;
var
i: integer;
begin
i:= 0;
while i < fCount do begin
if Key = fKeys[i] then exit(false); // Key already exists
//Todo: replace with binary search
if Key < fKeys[i] then begin
// Make space for the key
Move(fKeys[i], fKeys[i+1], (fCount - i) * SizeOf(TKey));
// If the key is a String or DynArray zero out the pointer
if (SizeOf(K) = SizeOf(NativeInt)) then NativeInt((@fKeys[i])^):= 0;
// If the value is a String or DynArray zero out the pointer
Move(fValues[i], fValues[i+1], (fCount - i) * SizeOf(V));
if (SizeOf(V) = SizeOf(NativeInt)) then NativeInt((@fValues[i])^):= 0;
break;
end;
Inc(i);
end; { while }
Inc(fCount);
//ClearKey(fKeys[i]);
fKeys[i]:= Key;
// if ValueType = tkUString then UniqueString(PString(@fValues[i])^);
fValues[i]:= Value;
Result:= true;
end;
如果树将字符串保存为K或V类型,则指针需要归零。
move
击败COW机制,2个字符串将具有新值。
关于上述if then
的好处是编译器消除了测试。
BPlusTrees.pas.454: if (SizeOf(K) = SizeOf(NativeInt)) then NativeInt((@fKeys[i])^):= 0;
0056BBC4 8B4610 mov eax,[esi+$10] //Test is eliminated by compiler.
0056BBC7 8D0498 lea eax,[eax+ebx*4]
0056BBCA 33D2 xor edx,edx
0056BBCC 8910 mov [eax],edx
因为可以在编译时解析SizeOf,所以编译器可以看到测试总是解析为true
(或者为false)并将消除它。
然而
上面的代码只需要运行引用计数类型,即:接口,字符串和dynarrays
现在它也运行整数,对象等。
TypeInfo
的问题在于它生成的检查代码比我试图避免的实际代码花费的时间更长。
BPlusTrees.pas.454: if (SizeOf(K) = SizeOf(NativeInt)) and
(PTypeInfo(TypeInfo(K))^.Kind <> tkInteger)
then NativeInt((@fKeys[i])^):= 0;
0056BBC4 A19C104000 mov eax,[$0040109c]
0056BBC9 803801 cmp byte ptr [eax],$01
0056BBCC 740A jz $0056bbd8
0056BBCE 8B4610 mov eax,[esi+$10]
0056BBD1 8D0498 lea eax,[eax+ebx*4]
0056BBD4 33D2 xor edx,edx
0056BBD6 8910 mov [eax],edx
有没有办法缩小上面的测试范围,以便测试表达式仍然可以在编译时解析,以便它编译成与上面相同的代码但排除更多类型?
我已经了解了内在的惯例,但我看不到任何可以帮助我的事情:http://docwiki.embarcadero.com/RADStudio/XE4/en/Delphi_Intrinsic_Routines
答案 0 :(得分:2)
在编译时,没有办法区分无约束的泛型类型。在编译时没有可以从非托管类型告知托管类型的运算符。
<强>更新强>
自XE7以来,有一个新的内在IsManagedType
旨在满足您的需求。迄今为止,这种内在的无证。也许最好的参考是:http://delphisorcery.blogspot.co.uk/2014/10/new-language-feature-in-xe7.html?m=1