I would like to be able to create enums of struct types, but it doesn't seem possible at the moment. You can create manifest constants of a struct using enum, but not an enum with an actual list of values. So, if I were to create a struct that looks like this
struct S
{
this(string phrase, int num)
{
this.phrase = phrase;
this.num = num;
}
int opCmp(const ref S rhs)
{
if(phrase < rhs.phrase)
return -1;
else if(phrase > rhs.phrase)
return 1;
if(num < rhs.num)
return -1;
else if(num > rhs.num)
return 1;
return 0;
}
string phrase;
int num;
}
I could create enums like this
enum a = S("hello", 1);
enum b = S("goodbye", 45);
and the compiler is fine with it. However, if I try and create a bona fide enum
enum E : S {a = S("hello", 1),
b = S("goodbye", 45),
c = S("world", 22)};
the compiler complains like so
t.d(28): Error: variable __ctmp1 cannot be read at compile time
t.d(28): Error: cannot evaluate __ctmp1.this("hello",1) at compile time
t.d(28): Error: cannot evaluate __ctmp1.this("hello",1) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(29): Error: Integer constant expression expected instead of __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) < 0
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(29): Error: Integer constant expression expected instead of __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) > 0
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(30): Error: cannot evaluate __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(30): Error: Integer constant expression expected instead of __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) < 0
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(30): Error: cannot evaluate __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(30): Error: Integer constant expression expected instead of __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) > 0
It doesn't look like the CTFE stuff can handle this for some reason. Granted, what CTFE can do is a definite work in progress, but I think that the lack of ability to create an enum of structs is seriously limiting and rather odd given that you can create a manifest constant of a struct using an enum. So, I'd love it if it were possible to create actual enums of a struct type.
Comment #1 by issues.dlang — 2010-11-28T20:48:56Z
I'm elevating this to a bug, since TDPL clearly says that you can have enums of struct types.
Comment #2 by issues.dlang — 2011-06-19T20:09:48Z
Why is this assigned to Andrei of all people? As far as I know, he never does any work on the compiler.
Comment #3 by andrei — 2011-06-20T06:02:50Z
Resetting asignee to default.
Comment #4 by clugdbug — 2011-06-29T01:38:57Z
This works in git master, if opCmp has signature
int opCmp(S rhs) instead of
int opCmp(const ref S rhs).
The problem lies in enum.c, which tries to determine max and min for the enum by comparing the each element in the enum. Since they are struct literals, they aren't lvalues, so 'const ref' fails.
This is an example of bug 6221.
Comment #5 by andrej.mitrovich — 2014-01-06T12:55:14Z
The OP sample now works.
Off-topic: Can someone explain to me why Bugzilla keeps logging me out every 10 minutes? Isn't there a way to enable persistent cookies or something? I don't see an option for it in the settings.
Comment #6 by hsteoh — 2014-08-07T20:40:59Z
Works in git HEAD. Full test code:
------
struct S
{
this(string phrase, int num)
{
this.phrase = phrase;
this.num = num;
}
int opCmp(const ref S rhs)
{
if(phrase < rhs.phrase)
return -1;
else if(phrase > rhs.phrase)
return 1;
if(num < rhs.num)
return -1;
else if(num > rhs.num)
return 1;
return 0;
}
string phrase;
int num;
}
enum E : S {a = S("hello", 1),
b = S("goodbye", 45),
c = S("world", 22)};
void main() {
import std.stdio;
E e;
writeln(e.phrase);
e = E.b;
writeln(e.phrase);
}
------
Program output:
------
hello
goodbye
------
Comment #7 by github-bugzilla — 2014-08-10T12:54:37Z