Identifier not found "TMyOrdinalType"
workaround is not to use macros.I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
however this does not compile:I don’t understand why you aren’t writing a simple type alias:
May I ask you why is that?workaround is not to use macros.I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
I don’t understand why you aren’t writing a simple type alias:
type TMyOrdinalType = Byte;
I have also said my self that it's not elegant and that's the reason why I would like to avoid it. Unfortunately {$if SizeOf(TMyOrdinalType) = 1} doesn't work although according to $IF docs I expected it to work. I discuss this case here to find out if I should file a bug report, or to find out a more elegant alternative.May I ask you why is that?workaround is not to use macros.I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
Because from your sample it smells like C preprocessor meta-programming which is everything but elegant.
Мне интересно: вы смотрите конечный код (скомпилированный) - что получается на выходе такого кода?!
function TORDINALHELPER.HighestBitPos: cardinal; begin {$if SizeOf(TORDINALTYPE) = 1} Result := BsrByte(byte(Self)); {$elseif SizeOf(TORDINALTYPE) = 2} Result := BsrWord(word(Self)); {$elseif SizeOf(TORDINALTYPE) = 4} Result := BsrDWord(dword(Self)); {$else} // SizeOf(TORDINALTYPE) = 8 Result := BsrQWord(qword(Self)); {$endif} end;
*snip*I see. It looks to me as a perfect case for using template specialization (as marcov noted).I have also said my self that it's not elegant and that's the reason why I would like to avoid it. Unfortunately {$if SizeOf(TMyOrdinalType) = 1} doesn't work although according to $IF docs I expected it to work. I discuss this case here to find out if I should file a bug report, or to find out a more elegant alternative.May I ask you why is that?workaround is not to use macros.I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
Because from your sample it smells like C preprocessor meta-programming which is everything but elegant.
Alternatively, make it generic and then use gettypekind ?Looking at TTypeKind I do not see how can ordinal types with SysUtils helpers (boolean type are not interesting) be identified as 1, 2 4 or 8 bytes (for example byte and shortint can not be identified as 1 byte types, and word and smallint as 2 byte types).
I'm wondering: you are looking at the final code (compiled) - what is the output of such a code?!No. According to documentation {$if SizeOf(TORDINALTYPE) = 1} should be compilable but it's not. That's why I 'm looking at alternatives.
No. According to documentation {$if SizeOf(TORDINALTYPE) = 1} should be compilable but it can not be compiled. That's why I 'm looking at alternatives.
Ето нет конечный код. Kомпилированние не можно.
As said, I am trying to avoid runtime SizeOf() and case block check. The example I've shown is not probably going to end up in a loop, but I have examples where even slightest delay matters a lot so I am trying to optimize for performance as much as it's reasonable and stays cross platform.No. According to documentation {$if SizeOf(TORDINALTYPE) = 1} should be compilable but it can not be compiled. That's why I 'm looking at alternatives.
Ето нет конечный код. Kомпилированние не можно.
It should be if defined as type alias, but you are turning it into a macro. Doing it runtime with sizeof(T) CASE block might also help, and hope it is optimized away in final code. (because the sizeof(T) becomes a constant and the other case options will never happen)
*snip*
however this does not compile:and produces this compilation error:
{$MACRO ON} {$define TMyOrdinalType := byte} {$if SizeOf(TMyOrdinalType) = 1} WriteLn('SizeOf(TMyOrdinalType) = ', SizeOf(TMyOrdinalType)); {$endif} QuoteIdentifier not found "TMyOrdinalType"
Is there some workaround?
It really works, so I guess I should probably file a feature bug report. Thanks a lot! :D :) :DI'm not sure it is a bug. IMHO I'd prefer not to have a macro expansion within a conditional directive. I even wonder why {$DEFINE :=} was introduced at first place, we have const, type ... In C that was the only way to define (literal) constants.
It really worksExample works, but redeclaring types is not possible so not applicable to my specific use case:
It really works, so I guess I should probably file a feature bug report. Thanks a lot! :D :) :DI'm not sure it is a bug. IMHO I'd prefer not to have a macro expansion within a conditional directive. I even wonder why {$DEFINE :=} was introduced at first place, we have const, type ... In C that was the only way to define (literal) constants.
...and it would be even more useful if parameters were supported so that the message didn't have to be fixed.A small inline function could take a parameter and, being inline, its overhead would be very similar to that of a macro. Would that be helpful ?
...and it would be even more useful if parameters were supported so that the message didn't have to be fixed.A small inline function could take a parameter and, being inline, its overhead would be very similar to that of a macro. Would that be helpful ?
As said, I am trying to avoid runtime SizeOf() and case block check.
I don't think so in that specific case, since the error message (assertion) would still indicate the point of definition rather than the point of invocation.True but, you could pass the line number as a parameter to the inline function.
The case statement is being passed a constant, so the compiler knows exactly what the value is and can optimize away all of the unused cases at compile-time, thus leaving only the 1 usable case to be executable at runtime.If that is so then it is tempting to let compiler handle it, however for this specific case I will choose more control over less control.
I don't think so in that specific case, since the error message (assertion) would still indicate the point of definition rather than the point of invocation.True but, you could pass the line number as a parameter to the inline function.
Возник ещё один вопрос: а для чего это вообще можно использовать? Мы заранее знаем, что размерность байта равна единице, и так же знаем размерности других данных.
{$MACRO ON} {$if SizeOf(byte) = 1} WriteLn('SizeOf(byte) = ', SizeOf(byte)); {$endif}
why can it be used at all? We know in advance that the dimension of a byte is equal to one, and we also know the dimensions of other data.Original idea was to use {$if SizeOf(TMyOrdinalType) = 1} but since that didn't compile I quickly put several $if SizeOf tests to see what can actually pass. So {$if SizeOf(byte) = 1} and similar nonsenses are left overs after simple validation and confirmation tests. They do not have real use outside of testing.
The case statement is being passed a constant, so the compiler knows exactly what the value is and can optimize away all of the unused cases at compile-time, thus leaving only the 1 usable case to be executable at runtime.If that is so then it is tempting to let compiler handle it, however for this specific case I will choose more control over less control.
The use of a case-statement with either SizeOf(TORDINALTYPE) or SizeOf(Self) is in my opinion the most favored one as it doesn't rely on the preprocessor and thus looks nicer in codeIf affected code is longer then what can fit in a single view of the editor, then I completely agree. Otherwise I do not mind that much for simple and short code parts that do not tend to change much in the future.