Btw, if you only need one base type, then you don't even need the generic.
Can you elaborate on that ?... the majority of handles are ptruint (in Windows)...
Your solution depends on defining records, which works but it really isn't desirable... but that solves the "type" problem...
No it doesn't solve the type problem.
If you only need Ptruint, then you can define your "record wrapper" as a normal record instead of as a generic.
But you still have do then do
TMFooHandle = type TMWrapper;
And that still has the issue of not copying all operators.
Mind that with the generic, even though you have a specialize on each declaration, that does not create new types.
var
a: specialize TFoo<byte>;
b: specialize TFoo<byte>;
gives the same type to a and b.
The 2nd specialize re-uses the same type that already exists. That is why you can specialize inline, even do stuff like (if TFoo was a class): begin a := specialize TFoo<byte>.create;
However since it is just the explicit operator that does not get copied....
You can declare the := operator. That seems to get copied.
class operator :=(const i: integer): TTypeWrapper;
That also allows typecasts.
Just unfortunately it also allows
TFooHandle := 0; // without typecast.
but different handles are still incompatible.