www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 10814] New: Formatting string-based enum prints its name instead of its value

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10814

           Summary: Formatting string-based enum prints its name instead
                    of its value
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: nobody puremagic.com
        ReportedBy: andrej.mitrovich gmail.com


--- Comment #0 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2013-08-13
02:17:00 PDT ---
-----
import std.stdio;

enum Type : string
{
    button = "type::button",
}

void main()
{
    writeln(Type.button);

    writefln("%s", Type.button);

    writeln(cast(string)Type.button);
}
-----

Prints:
button
button
type::button

It's really strange that we have to cast an enum just to retrieve the actual
value.

Note for example what happens when you use '%d' on an enum:

-----
import std.stdio;

enum Type : int
{
    button = 1,
}

void main()
{
    writefln("%s", Type.button);
    writefln("%d", Type.button);
}
-----

Prints:
button
1

However you can't use this trick for string enums since there's no equivalent
format specifier to retrieve an actual string.

There should be a way to always format the actual value of an enum in
writef/format calls. "%s" might try to do the convenient thing by default, so
maybe a new format specifier would be required? E.g. "%e" for enum values.

Alternatively one would write a helper template, e.g. toBaseValue(enumVal),
which would return the base type value of an enum:

-----
import std.stdio;

enum Type : int
{
    button = 1,
}

enum Type2 : string
{
    button = "ttk::button",
}

template EnumBaseType(E) if (is(E == enum))
{
    static if (is(E B == enum))
        alias EnumBaseType = B;
}

T toBaseType(E, T = EnumBaseType!E)(E val)
{
    return cast(T)val;
}

void main()
{
    writefln("%s %s", Type.button.toBaseType, Type2.button.toBaseType);
}
-----

Prints:
1 ttk::button

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 13 2013
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10814


rswhite4 googlemail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rswhite4 googlemail.com


--- Comment #1 from rswhite4 googlemail.com 2013-08-13 02:39:18 PDT ---
Another Workaround:

----
import std.stdio;

enum Type : string
{
   button = "type::button",
}

void main()
{
    writeln("" ~ Type.button);
}
----

prints:
type::button

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 13 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10814



--- Comment #2 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2013-08-13
03:56:19 PDT ---
(In reply to comment #1)
 Another Workaround:
     writeln("" ~ Type.button);
Well, that might even allocate. I thought slicing could work too, but the following doesn't compile: writeln(Type.button[]); Error: template std.stdio.writeln(T...)(T args) cannot deduce template function from argument types !()(Type) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 13 2013