Subtyping of an enum

Alex sascha.orlov at gmail.com
Mon Apr 15 10:00:36 UTC 2019


On Monday, 15 April 2019 at 08:39:24 UTC, Anton Fediushin wrote:
> Hello! I am currently trying to add a custom `toString` method 
> to an enum so that:
> 1. Enum members would still have numeric values and can be 
> easily compared (things like `enum a { foo = "FOO", bar = 
> "BAR”}` won't do, I want `a.foo < a.bar)`)
> 2. More custom methods can be implemented in the future
>
> Obvious solution is to wrap an enum in a structure and utilize 
> 'alias this' for subtyping like this:
> ```
> struct Enum {
>   private {
>     enum internal {
>       foo,
>       bar
>     }
>     internal m_enum;
>   }
>   this(internal i) { m_enum = i; }
>   alias m_enum this;
>   string toString() {
>     // custom implementation of toString
>   }
> }
> ```
>
> This seems to work just fine for assigning and comparisons but 
> passing Enum as a function argument does not work:
> ```
> void fun(Enum e) {}
>
> fun(Enum.foo);
> ---
> Error: function fun(Enum e) is not callable using argument 
> types (internal)
> Cannot pass argument foo of type internal to parameter Enum e.
> ```
>
> Of course, I could just define a bunch of functions that accept 
> my enum as the first argument and call them using UFCS but it'd 
> require to explicitly specify functions instead of D taking 
> care of that (toString() for structures is called automagically 
> by functions like writeln) and those functions would hang 
> around here and there totally unorganized. I prefer to keep 
> functions inside of structures and classes.

Isn't this a reason for passing your internals encapsulated, like

´´´
Enum EnumInstance = Enum(Enum.internal.foo);
fun(EnumInstance);
´´´

?

>
> If there are other ways of achieving the same *and* keeping 
> code clean and organized, please share.
>
> Thank you in advance,
> Anton.

Otherwise, you could alwas define fun as

´´´
void fun(Enum.internal e) {}
´´´

but I assume, you want to avoid especially this.

In favor of my first proposition, also speaks the fact, that 
Enum.foo is somewhat awkward w.r.t. your question, as you treat 
the internal enum as a static member. Was this intended?



More information about the Digitalmars-d-learn mailing list