Passing a pointer parameter

Is it possible to write a method that takes any ordinal type as a parameter? Just like Inc () or High ()?

I am using Delphi 2007

+4
source share
3 answers

You need to use an untyped parameter :

procedure Foo(const ordinal); 

or

 procedure Foo(var ordinal); 

Of course, you are somewhat limited by what you could do inside such a procedure, because you have abandoned the type system.

+6
source

The possible way found, maybe not the one you expect, but hey, I found a way! Use Variants . The problem with passing unprecedented parameters to the procedure is that you get a simple pointer, no type information, so there is nothing you can do about it. Bytes - 1 byte, enumerations up to 256 elements - 1 byte, enumerations up to 2 ^ 16 elements - 2 bytes, integers - 4 bytes (unless they are equal to 8). But there is one type that lets you pass in something and takes care of enough type information to make everything work: Variant . I intentionally wrote the following example in Delphi 7 to make sure that I do not accidentally use the goodness of Delphi 2010 or Delphi XE.

Edit: Updated sample code to handle any type that was reviewed by Ordinal using Variants.VarTypeIsOrdinal . This includes all integer types + Boolean. Obviously, Enum is treated as a byte, so it also swallows.

 program Project1; {$APPTYPE CONSOLE} uses ExceptionLog, SysUtils, Variants; type TSomeEnum = (e0, e1, e2, e3, e4); procedure DoSomethingWithEnum(V: Variant); var i: Integer; b: Byte; lw: LongWord; // Cardinal! i64: Integer; begin case VarType(V) of varInt64: begin i64 := V; WriteLn(i64); end; varSmallint, varInteger, varShortInt: begin i := V; WriteLn(i); end; varByte: begin b := V; WriteLn(b); end; varWord, varLongWord: begin lw := V; WriteLn(lw); end; varBoolean: begin if V then WriteLn('True') else WriteLn('False'); end; else WriteLn('NOT a variant type (type = #' + IntToStr(Ord(VarType(V)))); end; end; var i: Integer; b: Byte; c: Cardinal; enum: TSomeEnum; w: Word; si: Shortint; begin i := 1; b := 2; c := 3; enum := e4; w := 5; si := -6; DoSomethingWithEnum(i); DoSomethingWithEnum(b); DoSomethingWithEnum(c); DoSomethingWithEnum(enum); DoSomethingWithEnum(True); DoSomethingWithEnum(w); DoSomethingWithEnum(si); Readln; end. 
+1
source

The reason this is complicated is because Inc (x), Dec (x) and others like Pred (x) and Succ (x) are actually generated by the compiler and, if you like, just a Function style of syntactic sugar over the built-in compiler operation.

You can, as some people believe, make some of them overload, some of them with smart generics and some of them with options. But nothing will be convenient for emulating these functions or just as functionally.

The compiler implements Inc (), for example, for all ordered types, including Enums, Integer, and subranges on these types (now the rather obscure feature of the classic Pascal virtual is that all types can have subranges defined on these types).

If you really told us more about what you are doing, you may be closer. But the general answer: No, there is no source code for Inc and Dec, because these are compiler primitives. If the source code is RTL for the Inc function, you can look at it and adapt it.

inc (x) can be defined as x: = Succ (x), but then how do you define Succ (x)? How is x: = Inc (x)? You see. At some point, the magic compiler takes over.

0
source

Source: https://habr.com/ru/post/1346587/


All Articles