Bug 4423 – [tdpl] enums of struct types

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2010-07-04T03:23:00Z
Last change time
2014-08-10T12:54:45Z
Keywords
rejects-valid, TDPL
Assigned to
nobody
Creator
issues.dlang
Depends on
6221

Comments

Comment #0 by issues.dlang — 2010-07-04T03:23:53Z
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