3

I'm encoding a set type and a number into a (32-bit) Tag property. Retrieving the set from the Tag is trivial: TDaySet(Byte((tag and $ff000000) shr 24)). But how can I set up constants containing this encoded set information?

const
  FRED_SCHEDULE = ID_FRED or (Byte([Monday, Wednesday]) shl 24);

This doesn't compile. The actual error is "Invalid typecast" but I think the fundamental problem is that I'm trying to initialize a non-typed constant from a typed constant.

Has anyone a better idea?

Ian Goldby
  • 5,609
  • 1
  • 45
  • 81
  • [This answer](http://stackoverflow.com/a/9554208/127670) says that you can (typecast a set to an ordinal type) - but the type you cast to must be the same size. If there are only 7 days in the example above, I'd have to cast as a Byte rather than a Word. But that doesn't solve the const initialization problem. – Ian Goldby Jun 24 '13 at 13:07
  • Sorry. Taking back... – TLama Jun 24 '13 at 13:09
  • I think your assessment is correct. I played with this in FPC and FPC allows the typecast in an executable statement, as long as I used `longint` (it didn't like `byte` or `integer`). But when attempting a very simple constant expression, such as `FOO = longint([1,2,3]);` it balks ("illegal expression"). – lurker Jun 24 '13 at 14:34

1 Answers1

3

Well, first of all [Monday, Wednesday] is not a typed constant. It's not a typed constant because you did not declare a type. A typed constant would be

const
  Days: TSetOfDays = [Monday, Wednesday];

But, as you know, you cannot make a true constant out of a typed constant. And you cannot expect the compiler to know how to interpret [Monday, Wednesday] in your expression because you have not stated a type.

So, you cannot use set notation to declare a true constant, because you can only use set notation if you specify the type of the set. Which means that what you are attempting to do is probably not realistically possible. I mean, you could write this:

const
  FRED_SCHEDULE = ID_FRED 
    or ((1 shl ord(Monday) or 1 shl ord(Wednesday)) shl 24);

but it would be insane to do so.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Nitpickers corner: You **can** declare a true set constant. You just can't use that constant as needed here - which leaves me puzzled. – Uli Gerhardt Jun 24 '13 at 17:28
  • @Uli You can do it for integer base type perhaps? – David Heffernan Jun 24 '13 at 17:51
  • 1
    You can do `const cDays = [Monday, Wednesday]; var vDays: TSetOfDays; vDays := cDays; SomeByte := Byte(vDays);` but you can't replace the last statement with `SomeByte := Byte(cDays);` which I find extremely strange. (All AFAICR - no Delphi here :-)) – Uli Gerhardt Jun 24 '13 at 18:25
  • @Uli Well, what are Monday and Wednesday? I'm assuming enumerated types. – David Heffernan Jun 24 '13 at 20:39
  • That's what I implied. FWIW: I checked the assumptions from my last comment with XE2 and they are indeed correct. – Uli Gerhardt Jun 24 '13 at 20:53
  • @Uli I thought I tried that and such a constant was not valid. Must have mis-remembered. – David Heffernan Jun 24 '13 at 21:10
  • In the end I gave up on trying to use a set, and fell back on old-fashioned bitmasks. Boolean properties in a record allow me to access the various bits cleanly. – Ian Goldby Jun 26 '13 at 08:46