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?