View mode: basic / threaded / horizontal-split · Log in · Help
August 18, 2011
Safe enum conversions (again)
(This is a topic I've already discussed, this time I have a bit of code to show too.)

I sometimes have to perform run-time or compile-time conversions of enums, from the enum base type to the enum itself, and I'd like such conversions to be safe (this means no values outside the one listed in the enum get accepted).

I think this is a job for std.conv.to:
http://d.puremagic.com/issues/show_bug.cgi?id=5515

In Ada language there is a nice feature, you are allowed to define an enumerated set of chars, and then put string literals in your code that are typed as arrays of that char set. The Ada compiler verifies at compile-time the string contain only those allowed chars. This is useful for a compact and safe representation of tables, boards, and for other purposes.

I've seen that it's not too much hard to implement something similar in D too:


import std.traits: EnumMembers, OriginalType, Unqual;
import std.stdio: writeln;

private E[] enumConvert(E, T)(in T[] data) @safe pure nothrow
if (is(E == enum) && is(Unqual!T == OriginalType!Foo)) {
   //assert(__ctfe, "This is a compile-time function only.");

   E[T] dict;
   foreach (member; EnumMembers!E)
       dict[member] = member;

   auto result = new E[data.length];
   foreach (i, item; data)
       result[i] = dict[item];
   return result;
}

enum Foo : char { A='a', B='b', C='c' }

void show(T)(/*ref*/ T x) { // can't be ref
   writeln(x);
}

template F(string s) { // helper
   enum F = enumConvert!Foo(s);
}

void main() {
   enum Foo[9][2] foos = [F!"abcabcabc",
                          F!"cbacbacba"];

// not supported yet syntax, issue 481 and 3849
//    enum Foo[$][$] foos = [F!"abcabcabc",
//                           F!"cbacbacba"];

// not possible yet, issue 5515
//    import std.conv;
//    const Foo[] foos2 = to!(Foo[])("abcabcabc");

   show(foos); // [[A, B, C, A, B, C, A, B, C],
               //  [C, B, A, C, B, A, C, B, A]]
}


I think safe compile-time Enum conversion and safe run-time Enum conversion is a feature worth folding inside std.conv.to!().

Bye,
bearophile
Top | Discussion index | About this forum | D home