Why do TDateTime calculations involve variants?

96 Views Asked by At

Simple sample code below, with the generated assembler. I'm surprised that the generated code involves variants. The Delphi equivalent certainly doesn't.

TDateTime t1;
TDateTime t2;
...
int x =  2 * (t2 - t1);

Generated code.

Unit23.cpp.18: int x =  2 * (t2 - t1);
00401814 66C745C82400     mov word ptr [ebp-$38],$0024
0040181A 8D45DC           lea eax,[ebp-$24]
0040181D E852180000       call $00403074
00401822 50               push eax
00401823 FF45D4           inc dword ptr [ebp-$2c]
00401826 8D55A8           lea edx,[ebp-$58]
00401829 8D45A0           lea eax,[ebp-$60]
0040182C E8FB000000       call System::TDateTime::operator -(const System::TDateTime &)
00401831 DD5D94           fstp qword ptr [ebp-$6c]
00401834 8D5594           lea edx,[ebp-$6c]
00401837 8D45EC           lea eax,[ebp-$14]
0040183A E8F1180000       call $00403130
0040183F FF45D4           inc dword ptr [ebp-$2c]
00401842 8D55EC           lea edx,[ebp-$14]
00401845 B802000000       mov eax,$00000002
0040184A 59               pop ecx
***
0040184B E808010000       call System::operator *(int,const System::Variant &)
***
00401850 8D45DC           lea eax,[ebp-$24]
00401853 E8001A0000       call $00403258
00401858 89459C           mov [ebp-$64],eax
0040185B FF4DD4           dec dword ptr [ebp-$2c]
0040185E 8D45DC           lea eax,[ebp-$24]
00401861 BA02000000       mov edx,$00000002
00401866 E811190000       call $0040317c
0040186B FF4DD4           dec dword ptr [ebp-$2c]
0040186E 8D45EC           lea eax,[ebp-$14]
00401871 BA02000000       mov edx,$00000002
00401876 E801190000       call $0040317c
0040187B 66C745C81800     mov word ptr [ebp-$38],$0018
1

There are 1 best solutions below

0
mh taqia On BEST ANSWER

Note that the result of t2 - t1 is TDateTime and no operator has been defined to multiply int with TDateTime, In this circumstance compiler applies unwanted conversions/casts. Both of operands have been casted to Variant and this global scope operator is called (int on left):

Variant __fastcall operator *(int lhs, const Variant& rhs)
{
    return Variant(lhs).operator *(rhs);
}

I recommend you to prevent unwanted casts by specifing operand type, thus you should change the expression as:

int x =  2 * (t2 - t1).Val;

or

int x =  2 * (int)(t2 - t1);

or

int x =  2 * (t2.Val - t1.Val); // best, minimum assembly is generated