Thread overview
Value of type enum members
Jan 19, 2021
Andrey Zherikov
Jan 19, 2021
Paul Backus
January 19, 2021
Could someone please explain why there is a difference in values between compile-time and run-time?


struct T
{
    int i;
    this(int a) {i=a;}
}

enum TENUM : T
{
    foo = T(2),
    bar = T(3),
}

void main()
{
    pragma(msg, TENUM.foo);    // T(2)
    pragma(msg, TENUM.bar);    // T(3)
    writeln(TENUM.foo);        // foo
    writeln(TENUM.bar);        // bar
}
January 19, 2021
On Tuesday, 19 January 2021 at 20:27:30 UTC, Andrey Zherikov wrote:
> Could someone please explain why there is a difference in values between compile-time and run-time?
>
[...]
> void main()
> {
>     pragma(msg, TENUM.foo);    // T(2)
>     pragma(msg, TENUM.bar);    // T(3)
>     writeln(TENUM.foo);        // foo
>     writeln(TENUM.bar);        // bar
> }

There is no difference in the values, they're just being printed differently. pragma(msg) uses the compiler's internal string-conversion routines, and writeln uses the ones from Phobos, so it's not too surprising that they would display some values differently.
January 19, 2021
On Tuesday, 19 January 2021 at 20:27:30 UTC, Andrey Zherikov wrote:
> Could someone please explain why there is a difference in values between compile-time and run-time?
>
>
> struct T
> {
>     int i;
>     this(int a) {i=a;}
> }
>
> enum TENUM : T
> {
>     foo = T(2),
>     bar = T(3),
> }
>
> void main()
> {
>     pragma(msg, TENUM.foo);    // T(2)
>     pragma(msg, TENUM.bar);    // T(3)
>     writeln(TENUM.foo);        // foo
>     writeln(TENUM.bar);        // bar
> }

TL;DR `pragma(msg, x)` prints the value of `x` usually casted to the enumeration (base) type, while `std.conv.to!string(x)` prints the name of the enum member corresponding to the value of `x`.

Both `pragma(msg, ...)` and `std.conv.to!string(..)` (what is used under the hood by `writeln(..)`) take somewhat arbitrary decisions about formating enum members, neither of which is the "right" one, as there's no rule saying which is better.

In general, `std.conv.to!string(..)` tries to use format that is meant to be friendly to the end-users of your program, while `pragma(msg, ...)` is a CT debugging tool and it tries to stay close to the compiler's understanding of your program.

For example:

void main()
{
    import std.stdio;

    enum E1 { a = 1, b, c }
    enum E2 { x = "4" }
    enum E3 : string { y = "5" }

    // 1.0 2L cast(E1)3 4 5
    pragma(msg, 1.0, " ", long(2), " ", E1.c, " ", E2.x, " ", E3.y);

    // 1 2 c x y
    writeln(1.0, " ", long(2), " ", E1.c, " ", E2.x, " ", E3.y);
}


End-users generally don't care about the specific representations of numbers in your program, while on the other hand that's a crucial detail for the compiler and you can see this bias in the output.