Sadly the "Unreachable code" warning can not be suppressed
1. This is compiled only in the development version.
So? A potential Card() function or intrinsic would also only be part of trunk.
2. With {$mode objfpc} only two set sizes: 4 and 32. Thus, either one or the other part of "if" is an unreachable code.
Yes, I know, but I'm more complaining about that even with {$warn off 6018} around the generic function the compiler doesn't remember that setting when specializing the function which is quite irritating, cause I thought that this should work. Probably a bug I'll have to look at... *sigh*
3. With {$mode delphi} this code, with little modification, is wrong, because, as @Thaddy say "The unused bytes are undefined, i.e. also dirty".
program Project1;
{$APPTYPE CONSOLE}
{-$mode delphi}
{$mode objfpc}
{$IFDEF FPC_OBJFPC}generic{$ENDIF}
function Card<T>(const aSetValue: T): Integer;
var
i: Integer;
begin
Result := 0;
for i := 0 to SizeOf(T) - 1 do
Inc(Result, PopCnt(PByte(@aSetValue)[i]));
end;
type
TSet1 = set of 0..3;
TSet2 = set of 0..40;
var
set1: TSet1 = [2];
set2: TSet2 = [4, 9, 23, 40];
begin
set1 := [2];
set2 := [4, 9, 23, 40];
Writeln(SizeOf(TSet1));
Writeln(SizeOf(TSet2));
Writeln({$IFDEF FPC_OBJFPC}specialize {$ENDIF}Card<TSet1>(set1));
Writeln({$IFDEF FPC_OBJFPC}specialize {$ENDIF}Card<TSet2>(set2));
Readln;
end.
Yes, that definitely simplifies that affair without any unreachable code warning. I was much too focused on the difference between small and large sets plus I wasn't aware that PopCnt had an overload for Byte as I had no need to use that function before.
Small additional improvement: Unlike Delphi FPC can also make use of "inline" here as long as the method implementation is encountered before it is first called (e.g. in the case above that works).