digitalmars.D - Bug 3999 and 4261
- bearophile (22/22) Aug 31 2010 Probably each of the ~25 bugs of the short list I have shown here recent...
- bearophile (11/11) Aug 31 2010 A way to tell them apart is the presence of the EnumTag, if it's present...
- Daniel Gibson (17/30) Aug 31 2010 I sometimes find it convenient to just treat those values as integers,
- Nick Sabalausky (22/33) Aug 31 2010 Better yet: stream.read!int()
- bearophile (4/5) Aug 31 2010 Yes, I am sure in some situations it can be handy. But it's a a bit of c...
- Daniel Gibson (8/15) Aug 31 2010 Then there still is the consistency-issue (anon. enums are treated
- bearophile (21/23) Aug 31 2010 Look at this:Se
- Daniel Gibson (11/14) Aug 31 2010 Why not use the non-fictional const keyword? "The const attribute
- bearophile (15/22) Aug 31 2010 I think it helps in a linker issue. But I am not expert on this. Maybe L...
- Daniel Gibson (11/44) Aug 31 2010 I know what you meant - but my point is that anon. enums make sense (I
- bearophile (22/30) Aug 31 2010 This compiles, here n is known at run-time only:
- Nick Sabalausky (3/13) Aug 31 2010 You were looking at the D1 docs. The whole const system changed in D2.
- Daniel Gibson (2/17) Sep 01 2010 http://www.digitalmars.com/d/2.0/attribute.html#const says the same.
- Nick Sabalausky (3/19) Sep 01 2010 Yea, that's probably wrong then. Unless there's something I don't know.
- Andrej Mitrovic (21/33) Aug 31 2010 This whole enum thing is making my head explode out of confusion. I
- Nick Sabalausky (9/13) Aug 31 2010 This is the way I've always seen an enum:
- Rainer Deyke (14/16) Sep 01 2010 In C++, const is used for both run-time and compile-time constants. In
- Don (3/19) Sep 01 2010 The enum situation exists ONLY because of linker limitations. It seems
- so (11/25) Sep 01 2010 I have never had troubles with C++ compile/runtime "const" difference,
- so (6/7) Sep 01 2010 This one.
- bearophile (4/5) Sep 01 2010 I have added it as bug 4786
- Jonathan M Davis (11/19) Sep 01 2010 C++ doesn't have CTFE. CTFE is why it really matters in D. If you're dea...
- Nick Sabalausky (3/8) Sep 01 2010 I find it to be a pain nearly every time I need to convert one to a stri...
- Jonathan M Davis (9/19) Sep 01 2010 I wasn't even aware that there was a way. If I had to guess, I would ass...
- Andrej Mitrovic (12/31) Sep 01 2010 I thought to!string(Enum) already does this? This was the example I
- Nick Sabalausky (4/15) Sep 01 2010 Does it really work that way now? That must have changed then. I could s...
- Andrej Mitrovic (3/21) Sep 01 2010 ear
- so (5/20) Sep 01 2010 Another taste discussion? Enum, again for "my taste" a great find for th...
- bearophile (9/11) Sep 01 2010 Nope.
- Andrei Alexandrescu (8/17) Sep 01 2010 I think it's a good enhancement. C++'s good old enum has been
- Nick Sabalausky (4/10) Sep 01 2010 "...it really means we're disabling implicit conversion"
- Andrei Alexandrescu (3/15) Sep 01 2010 It's bound to break some code.
- bearophile (10/19) Sep 01 2010 There is also the experience of the C++0x group of designers, and their ...
- Steven Schveighoffer (13/40) Sep 02 2010 Does this mean no more defining bits as enums?
- so (4/5) Sep 02 2010 Now that would be brutal, it is one of the best use cases of enum if not...
- Don (7/11) Sep 02 2010 Yes.
- bearophile (4/6) Sep 02 2010 See my recent answer to Schveighoffer. I think that's not a fully good i...
- Nick Sabalausky (5/15) Sep 02 2010 I think all the discussions we've had about enum make it clear that enum...
- bearophile (3/4) Sep 02 2010 I have used std.bitmanip.bitfields some time, and in my opinion its best...
- Don (9/17) Sep 02 2010 That's impossible. That would make interfacing to C a nightmare.
- Andrej Mitrovic (4/4) Sep 03 2010 I just stumbled upon this in std.typecons:
- bearophile (4/7) Sep 03 2010 Thank you. I think std.typecons.defineEnum() may be removed. I don't thi...
- Andrei Alexandrescu (4/11) Sep 03 2010 Yah, that artifact predates the introspection means that make printing
- Steven Schveighoffer (23/46) Sep 01 2010 AFAIK, enum meaning manifest constant was Andrei's request. And I think...
- Jonathan M Davis (15/40) Sep 01 2010 It's the kind of thing that is distasteful from a language purity standp...
- Nick Sabalausky (10/23) Sep 01 2010 Static is a little bit better in that the uses of it at least have some
- so (3/13) Sep 01 2010 Float is not floating and double is not doubling, are they next?
- Nick Sabalausky (9/20) Sep 01 2010 Float (short for "floating point"): The decimal point can "float" around...
- so (16/28) Sep 01 2010 I know what they are, but at the same time was expecting you to get the ...
- so (17/29) Sep 01 2010 If you throw "2.7f" on a water, does it float or you need to multiply wi...
- Nick Sabalausky (5/22) Sep 01 2010 Like I said, "metaphor". By contrast there's no basis for a metaphor bet...
- Nick Sabalausky (4/6) Aug 31 2010 Anon. enums *are* fundamentally different from named enums. It's already...
- Kagamin (3/4) Sep 01 2010 ??
- bearophile (4/8) Sep 01 2010 The whole point of this discussion about my enhancement request 3999 is ...
- Jonathan M Davis (7/20) Sep 01 2010 Well, like I said, it never occurred to me that you even could print enu...
- bearophile (52/66) Sep 02 2010 Thank you for that important use case. enum is used for three different ...
- bearophile (10/18) Sep 05 2010 That indeed happens, but from the code that I have seen the most common ...
Probably each of the ~25 bugs of the short list I have shown here recently need a bit of discussion (also because some of them are little breaking changes over current DMD and/or TDPL). Even if some of them may need to wait in Bugzilla for two years, it's positive to discuss them already. But you can't discuss all of them at the same time. This is one of them, chosen almost randomly, because it was recently commented by Andrej Mitrovic: http://d.puremagic.com/issues/show_bug.cgi?id=4261 It's related to: http://d.puremagic.com/issues/show_bug.cgi?id=3999 http://d.puremagic.com/issues/show_bug.cgi?id=3308 I think bug 3999 shows the root of the situation, so I focus on it (indeed bug 4261 was not in that short list). In C++0x Foo::V1 == 10 is a compile error, enum and int can't be compared (don't miss the 'class' there): enum class Foo { V1 = 10 }; int main() { int b = Foo::V1 == 10; } test.cpp: In function 'int main()': test.cpp:3: error: no match for 'operator==' in '(Foo)10 == 10' test.cpp:3: note: candidates are: operator==(int, int) <built-in> The point of the change suggested in bug 3999 is that this looks good to be adopted in D too. Enumerated sequences in my opinion are less bug-prone if they are true distinct types. -------------------- Note: despite in D unfortuntately constants and enumerated values share the same keyword, here I am not talking about constants like this one: enum int foo = 10; This foo is really of type int, it's not an enumeration, it's not a sequence of symbols of length 1 named foo. Semantically it is another thing (this is also why using the enum keyword for both things was the wrong choice). Bye, bearophile
Aug 31 2010
A way to tell them apart is the presence of the EnumTag, if it's present, then the enum is a new type: enum V1 = 10; enum { V2 = 20 } enum Foo { V3 } void main() { assert(V1 == 10); // OK assert(V2 == 20); // OK assert(Foo.V3 == 0); // ERROR, type mismatch } Bye, bearophile
Aug 31 2010
bearophile schrieb:A way to tell them apart is the presence of the EnumTag, if it's present, then the enum is a new type: enum V1 = 10; enum { V2 = 20 } enum Foo { V3 } void main() { assert(V1 == 10); // OK assert(V2 == 20); // OK assert(Foo.V3 == 0); // ERROR, type mismatch } Bye, bearophileI sometimes find it convenient to just treat those values as integers, e.g. when reading/writing them with a stream (to a file, to some other process with SocketStream, ...). Like --- int x; stream.read(x); // btw: this often sucks - why not x = stream.readInt()? if(x == MyEnum.DIE) return 0; else if(x == MyEnum.CALLFOO) foo(x); --- or something like that (switch() might be better, but whatever). Also treating named and unnamed enums differently seems inconsistent to me. Cheers, - Daniel
Aug 31 2010
"Daniel Gibson" <metalcaedes gmail.com> wrote in message news:mailman.24.1283298345.858.digitalmars-d puremagic.com...--- int x; stream.read(x); // btw: this often sucks - why not x = stream.readInt()?Better yet: stream.read!int()if(x == MyEnum.DIE) return 0; else if(x == MyEnum.CALLFOO) foo(x); --- or something like that (switch() might be better, but whatever). Also treating named and unnamed enums differently seems inconsistent to me.D's enums are *already* two completely different things. Some enums create a new type with a pre-determined set of possible values, and some *ahem* "enum"s *cough* just simply create a manifst constant and no new type. I gotta say, I'm completely with bearophile on these enum issues. One of the things that drew me to D from C/C++ is the increased emphasis on *strong* typing, but D's enums (and the death of typedef, athough I do understand the reasons for that) make me feel like I'm right back in the middle of C's shitty so-called "type system". Plus, even if you do want to treat a...*real* enum (such as MyEnum above) as little more than a series of manifest constants (which I think is terrible design for an enum system), then the whole point of them is to replace magic numbers with real names. So if they get printed out as their base type, then we're right back into useless "magic number" territory. I've never once, in any language, printed out the value of an enum variable, gotten the value of the *base* type, and *not* needed to convert that back into the enum symbol name either in my head or by looking up the enum definition (or mechanically). And I've rarely, if ever, in any language, printed out the value of an enum variable, gotten the actual symbol name and actually needed the value of the base type instead.
Aug 31 2010
Daniel Gibson:I sometimes find it convenient to just treat those values as integers,Yes, I am sure in some situations it can be handy. But it's a a bit of convenience that has a too much high price, the semantics is less clean, and it's more bug prone. So no thanks. Keeping things tidy is more important. Bye, bearophile
Aug 31 2010
bearophile schrieb:Daniel Gibson:Then there still is the consistency-issue (anon. enums are treated differently then named enums). Apart from that inconsistency: Yes, it wouldn't be unreasonable to just cast the int to MyEnum or the other way round for comparison. (or, in my example: MyEnum x; stream.read(cast(int)x); ...) Cheers, - DanielI sometimes find it convenient to just treat those values as integers,Yes, I am sure in some situations it can be handy. But it's a a bit of convenience that has a too much high price, the semantics is less clean, and it's more bug prone. So no thanks. Keeping things tidy is more important. Bye, bearophile
Aug 31 2010
Daniel Gibson:Then there still is the consistency-issue (anon. enums are treated differently then named enums).Look at this:Se enum int n = 10; enum Color { Red, Green, Blue } Color color; if (color == Color.Red) { ... Color is a sequence of symbols, Red, Green and Blue, named Color. When you write your program often all you need to know is if color is Red or Green, and you don't care much how the compiler represents those symbols. The n is a compile-time constant value. It's not a sequence of something. Now, just for fun, replace the first enum with something as: ctconst int n = 10; enum Color { Red, Green, Blue } Color color; if (color == Color.Red) { ... ctconst is a fictional keyword that denotes compile-time constants. Now you are probably able to see that there is no correlation between the n and Color. In D they are using the same keyword by accident, probably because Walter thinks that saving a keyword is more important than keeping the semantics tidy. So today you are probably struck with using "enum" to define compile-time constants. The C++0x design group has not introduced the "enum class" for fun, their strong typing nature is useful to make the code less bug-prone. See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1719.pdf See for example "Problem 1: Implicit conversion to an integer". Bye, bearophile
Aug 31 2010
bearophile wrote:ctconst is a fictional keyword that denotes compile-time constants. Now you are probably able to see that there is no correlation between the n and Color.Why not use the non-fictional const keyword? "The const attribute declares constants that can be evaluated at compile time."[1] "enum int n = 10;" looks really strange. I don't know if this is needed.. But "enum : int { FOO, BAR, BAZ };" does not look so strange to me and I'd prefer this to "const int FOO=0; const int BAR=1; const int BAZ=2;". The syntax is shorter, it shows that these keywords kind of belong together and the values are enumerated automatically. Cheers, - Daniel [1] http://www.digitalmars.com/d/1.0/attribute.html#const
Aug 31 2010
Daniel Gibson:Why not use the non-fictional const keyword? "The const attribute declares constants that can be evaluated at compile time."[1]But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time."enum int n = 10;" looks really strange. I don't know if this is needed..I think it helps in a linker issue. But I am not expert on this. Maybe LDC (based on LLVM) doesn't need enums much.But "enum : int { FOO, BAR, BAZ };" does not look so strange to me and I'd prefer this to "const int FOO=0; const int BAR=1; const int BAZ=2;". The syntax is shorter, it shows that these keywords kind of belong together and the values are enumerated automatically.I agree, and I have never said I want to disallow it. You can cast those FOO, BAR, etc implicitly to int. It's the example V2 I have shown, no error there: enum V1 = 10; enum { V2 = 20 } enum Foo { V3 } void main() { assert(V1 == 10); // OK assert(V2 == 20); // OK assert(Foo.V3 == 0); // ERROR, type mismatch } Thank you for your doubts and questions, they help me express better what I meant. It seems I was not clear enough at the beginning. Bye, bearophile
Aug 31 2010
bearophile schrieb:Daniel Gibson:Really? Than that definition from the language docs is inaccurate.Why not use the non-fictional const keyword? "The const attribute declares constants that can be evaluated at compile time."[1]But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.I know what you meant - but my point is that anon. enums make sense (I guess we agree on that one) and that allowing implicit casting to int for them and not for named enums seems inconsistent. Of course disallowing implicit casting for anon. enums is not really an options (how should that even work.. maybe "cast(enum:int)foo" or something like that..) so IMHO a reasonable solution is keeping it the way it is. Cheers, - Daniel"enum int n = 10;" looks really strange. I don't know if this is needed..I think it helps in a linker issue. But I am not expert on this. Maybe LDC (based on LLVM) doesn't need enums much.But "enum : int { FOO, BAR, BAZ };" does not look so strange to me and I'd prefer this to "const int FOO=0; const int BAR=1; const int BAZ=2;". The syntax is shorter, it shows that these keywords kind of belong together and the values are enumerated automatically.I agree, and I have never said I want to disallow it. You can cast those FOO, BAR, etc implicitly to int. It's the example V2 I have shown, no error there: enum V1 = 10; enum { V2 = 20 } enum Foo { V3 } void main() { assert(V1 == 10); // OK assert(V2 == 20); // OK assert(Foo.V3 == 0); // ERROR, type mismatch } Thank you for your doubts and questions, they help me express better what I meant. It seems I was not clear enough at the beginning. Bye, bearophile
Aug 31 2010
Daniel Gibson:Really? Than that definition from the language docs is inaccurate.This compiles, here n is known at run-time only: void main(string[] args) { const int n = args.length; } This compiles, but I think it's a bug: void main(string[] args) { enum int n = args.length; } This shows that there is a problem: template Foo(int n) { } void main(string[] args) { enum int n = args.length; alias Foo!(n) _; }I know what you meant - but my point is that anon. enums make sense (I guess we agree on that one) and that allowing implicit casting to int for them and not for named enums seems inconsistent.The real inconstancy is using 'enum' for them both in the first place. They are conceptually two different things. It looks inconsistent if you think of them as similar things. But even if you like to think of them as the same thing, you may think of my proposal as a way to enforce more strong typing, to remove a subset of the allowed behaviours of one subclass of those enum thinghies that you think are all the same thing. So you may see it as an inconstancy introduced on purpose to remove some risky behaviours. D has introduced some other of such 'inconsistencies' (compared to a uniform C behaviour) where they help disallow some behaviours that are regarded as negative.Of course disallowing implicit casting for anon. enums is not really an options (how should that even work.. maybe "cast(enum:int)foo" or something like that..)Right.so IMHO a reasonable solution is keeping it the way it is.In my opinion (and probably in the opinion of the people that are designing C++x0) this is not a good enough solution, because it's a little error-prone. Bye, bearophile
Aug 31 2010
"Daniel Gibson" <metalcaedes gmail.com> wrote in message news:i5kbpr$24tn$1 digitalmars.com...bearophile schrieb:You were looking at the D1 docs. The whole const system changed in D2.Daniel Gibson:Really? Than that definition from the language docs is inaccurate.Why not use the non-fictional const keyword? "The const attribute declares constants that can be evaluated at compile time."[1]But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.
Aug 31 2010
Nick Sabalausky schrieb:"Daniel Gibson" <metalcaedes gmail.com> wrote in message news:i5kbpr$24tn$1 digitalmars.com...http://www.digitalmars.com/d/2.0/attribute.html#const says the same.bearophile schrieb:You were looking at the D1 docs. The whole const system changed in D2.Daniel Gibson:Really? Than that definition from the language docs is inaccurate.Why not use the non-fictional const keyword? "The const attribute declares constants that can be evaluated at compile time."[1]But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.
Sep 01 2010
"Daniel Gibson" <metalcaedes gmail.com> wrote in message news:i5lrkr$1ijr$1 digitalmars.com...Nick Sabalausky schrieb:Yea, that's probably wrong then. Unless there's something I don't know."Daniel Gibson" <metalcaedes gmail.com> wrote in message news:i5kbpr$24tn$1 digitalmars.com...http://www.digitalmars.com/d/2.0/attribute.html#const says the same.bearophile schrieb:You were looking at the D1 docs. The whole const system changed in D2.Daniel Gibson:Really? Than that definition from the language docs is inaccurate.Why not use the non-fictional const keyword? "The const attribute declares constants that can be evaluated at compile time."[1]But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.
Sep 01 2010
This whole enum thing is making my head explode out of confusion. I thought having a tag was just supossed to be used as a namespace for enumerated values. E.g.: enum { red =3D 1, green, blue } ... if (getValue() =3D=3D green) { do.. } and: enum Tagged { red =3D 1, green, blue } ... if (getValue() =3D=3D Tagged.green) { // safer version do.. } That is all that I thought enums are useful for. But apparently an enum is a type and you can instantiate it.... and I don't even know what an enum is anymore. I'll just stay out of this discussion for now, lol. :)I agree, and I have never said I want to disallow it. You can cast those =FOO, BAR, etc implicitly to int. It's the example V2 I have shown, no error= there:enum V1 =3D 10; enum { V2 =3D 20 } enum Foo { V3 } void main() { =A0 =A0assert(V1 =3D=3D 10); =A0 =A0// OK =A0 =A0assert(V2 =3D=3D 20); =A0 =A0// OK =A0 =A0assert(Foo.V3 =3D=3D 0); // ERROR, type mismatch } Thank you for your doubts and questions, they help me express better what=I meant. It seems I was not clear enough at the beginning.Bye, bearophile
Aug 31 2010
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.28.1283307608.858.digitalmars-d puremagic.com...That is all that I thought enums are useful for. But apparently an enum is a type and you can instantiate it.... and I don't even know what an enum is anymore. I'll just stay out of this discussion for now, lol. :)This is the way I've always seen an enum: An enum is a custom type with a pre-defined set of possible values, each individually-named. That's the primary purpose. Typically, an enum will have a "base" type which determines the physical in-memory representation of the values and allows for a convenient (but not accidentally-invoked) one-to-one mapping between the enum values and certain values from one other user-chosen type (ie, the base type).
Aug 31 2010
On 8/31/2010 19:46, bearophile wrote:But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.In C++, const is used for both run-time and compile-time constants. In practice, this works out fine. It its value can only be known at run-time, it's a run-time constant. If its value is used at compile-time, it's a compile-time constant. If both of these apply, it's an error. If neither applies, nobody cares if it's a compile-time or run-time constant. (The actual rules in C++ are a bit more complex, less intuitive, and less useful than that, which is presumably why Walter chose not to copy the C++ in this case. Still, overloading 'const' for both compile-time and run-time constants is viable, and more intuitive than the current situation with 'enum'.) -- Rainer Deyke - rainerd eldwood.com
Sep 01 2010
Rainer Deyke wrote:On 8/31/2010 19:46, bearophile wrote:The enum situation exists ONLY because of linker limitations. It seems most people still don't understand that.But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.In C++, const is used for both run-time and compile-time constants. In practice, this works out fine. It its value can only be known at run-time, it's a run-time constant. If its value is used at compile-time, it's a compile-time constant. If both of these apply, it's an error. If neither applies, nobody cares if it's a compile-time or run-time constant. (The actual rules in C++ are a bit more complex, less intuitive, and less useful than that, which is presumably why Walter chose not to copy the C++ in this case. Still, overloading 'const' for both compile-time and run-time constants is viable, and more intuitive than the current situation with 'enum'.)
Sep 01 2010
On Wed, 01 Sep 2010 11:06:51 +0300, Rainer Deyke <rainerd eldwood.com> wrote:On 8/31/2010 19:46, bearophile wrote:I have never had troubles with C++ compile/runtime "const" difference, and don't think it is a problem in C++. With this in mind "enum" is a great keyword of choice to express compile-time types, as long as it is forbidden for run-time constants. (I hope that example of bearophile is just a bug.) Thanks. -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/But you can use const for constants that are known at run-time only. While you can't use enum for constant known at run-time.In C++, const is used for both run-time and compile-time constants. In practice, this works out fine. It its value can only be known at run-time, it's a run-time constant. If its value is used at compile-time, it's a compile-time constant. If both of these apply, it's an error. If neither applies, nobody cares if it's a compile-time or run-time constant. (The actual rules in C++ are a bit more complex, less intuitive, and less useful than that, which is presumably why Walter chose not to copy the C++ in this case. Still, overloading 'const' for both compile-time and run-time constants is viable, and more intuitive than the current situation with 'enum'.)
Sep 01 2010
(I hope that example of bearophile is just a bug.)This one. void main(string[] args) { enum int n = args.length; } -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Sep 01 2010
so:(I hope that example of bearophile is just a bug.)I have added it as bug 4786 Bye, bearophile
Sep 01 2010
On Wednesday, September 01, 2010 11:58:39 so wrote:I have never had troubles with C++ compile/runtime "const" difference, and don't think it is a problem in C++. With this in mind "enum" is a great keyword of choice to express compile-time types, as long as it is forbidden for run-time constants. (I hope that example of bearophile is just a bug.) Thanks.C++ doesn't have CTFE. CTFE is why it really matters in D. If you're dealing with a compile-time constant, it uses CTFE. If you're dealing with a runtime constant, it doesn't. So, you need to be explicit. Personally, I don't really care about using enum the way it is. Having enums freely converting to and from their base type is more of a concern, though I'm not sure how much that really does or doesn't matter. It's quite clear when an enum is used as a manifest constant and when it's used as an enum, so I don't really see a problem with the way it is, though I can see why someone wouldn't like it. - Jonathan M Davis
Sep 01 2010
"Jonathan M Davis" <jmdavisprog gmail.com> wrote in message news:mailman.33.1283368612.858.digitalmars-d puremagic.com...Personally, I don't really care about using enum the way it is. Having enums freely converting to and from their base type is more of a concern, though I'm not sure how much that really does or doesn't matter.I find it to be a pain nearly every time I need to convert one to a string.
Sep 01 2010
On Wednesday, September 01, 2010 12:59:01 Nick Sabalausky wrote:"Jonathan M Davis" <jmdavisprog gmail.com> wrote in message news:mailman.33.1283368612.858.digitalmars-d puremagic.com...I wasn't even aware that there was a way. If I had to guess, I would assume that it involves stringof, but I'd have to try it. Now, assuming that that's the case, it would be pretty easy to write a template function which takes the enum type and the value to stringify, and it returns the string version of that enum value (or throws if it's not a valid value for that enum type). I can see how having it as a distinct type would be more desirable for that though, since then you could likely just use stringof on it directly. - Jonathan M DavisPersonally, I don't really care about using enum the way it is. Having enums freely converting to and from their base type is more of a concern, though I'm not sure how much that really does or doesn't matter.I find it to be a pain nearly every time I need to convert one to a string.
Sep 01 2010
I thought to!string(Enum) already does this? This was the example I posted in bug report 4261: import std.conv : to; import std.stdio: writeln; void main() { enum Foo { Zero, One } Foo f = Foo.One; writeln(to!string(f)); } Prints: One On Wed, Sep 1, 2010 at 10:50 PM, Jonathan M Davis <jmdavisprog gmail.com> wrote:On Wednesday, September 01, 2010 12:59:01 Nick Sabalausky wrote:"Jonathan M Davis" <jmdavisprog gmail.com> wrote in message news:mailman.33.1283368612.858.digitalmars-d puremagic.com...I wasn't even aware that there was a way. If I had to guess, I would assume that it involves stringof, but I'd have to try it. Now, assuming that that's the case, it would be pretty easy to write a template function which takes the enum type and the value to stringify, and it returns the string version of that enum value (or throws if it's not a valid value for that enum type). I can see how having it as a distinct type would be more desirable for that though, since then you could likely just use stringof on it directly. - Jonathan M DavisPersonally, I don't really care about using enum the way it is. Having enums freely converting to and from their base type is more of a concern, though I'm not sure how much that really does or doesn't matter.I find it to be a pain nearly every time I need to convert one to a string.
Sep 01 2010
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.49.1283374449.858.digitalmars-d puremagic.com...I thought to!string(Enum) already does this? This was the example I posted in bug report 4261: import std.conv : to; import std.stdio: writeln; void main() { enum Foo { Zero, One } Foo f = Foo.One; writeln(to!string(f)); } Prints: OneDoes it really work that way now? That must have changed then. I could swear it wasn't like that before.
Sep 01 2010
That's how it's described in TDPL, and yes it works. On Wed, Sep 1, 2010 at 11:38 PM, Nick Sabalausky <a a.a> wrote:"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.49.1283374449.858.digitalmars-d puremagic.com...earI thought to!string(Enum) already does this? This was the example I posted in bug report 4261: import std.conv : to; import std.stdio: writeln; void main() { =A0 =A0enum Foo { Zero, One } =A0 =A0Foo f =3D Foo.One; =A0 =A0writeln(to!string(f)); } Prints: OneDoes it really work that way now? That must have changed then. I could sw=it wasn't like that before.
Sep 01 2010
ctconst is a fictional keyword that denotes compile-time constants. Now you are probably able to see that there is no correlation between the n and Color. In D they are using the same keyword by accident, probably because Walter thinks that saving a keyword is more important than keeping the semantics tidy. So today you are probably struck with using "enum" to define compile-time constants. The C++0x design group has not introduced the "enum class" for fun, their strong typing nature is useful to make the code less bug-prone. See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1719.pdf See for example "Problem 1: Implicit conversion to an integer". Bye, bearophileAnother taste discussion? Enum, again for "my taste" a great find for the job. Bugs aside, i can't seem to follow you. -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Sep 01 2010
so:Another taste discussion?Nope. ----------------- Steven Schveighoffer:And I think if you have an idea to try and "fix" it, you might as well know now, it will never happen.<There I was explaining something better to Daniel Gibson. The purpose of the enhancement request 3999 has nothing to do with a request for a different keyword. ----------------- I think now I have presented my point as well as I can, and people have given comments and opinions. I'd like to Walter or/and Andrei to express their opinion about the bug 3999 :-) Bye, bearophile
Sep 01 2010
On 9/1/10 15:35 CDT, bearophile wrote:so:I think it's a good enhancement. C++'s good old enum has been instrumental in finding a few bugs and clarifying a few interfaces in a project at work. Based on that experience I'd say that there's a chance more restrictive is better. We need to find a principled way to define semantics though - if we disable comparison it really means we're disabling implicit conversion. AndreiAnother taste discussion?Nope. ----------------- Steven Schveighoffer:And I think if you have an idea to try and "fix" it, you might as well know now, it will never happen.<There I was explaining something better to Daniel Gibson. The purpose of the enhancement request 3999 has nothing to do with a request for a different keyword. ----------------- I think now I have presented my point as well as I can, and people have given comments and opinions. I'd like to Walter or/and Andrei to express their opinion about the bug 3999 :-)
Sep 01 2010
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:i5mfji$2qtd$1 digitalmars.com...I think it's a good enhancement. C++'s good old enum has been instrumental in finding a few bugs and clarifying a few interfaces in a project at work. Based on that experience I'd say that there's a chance more restrictive is better. We need to find a principled way to define semantics though - if we disable comparison it really means we're disabling implicit conversion."...it really means we're disabling implicit conversion" And that's a problem?
Sep 01 2010
On 9/1/10 16:39 CDT, Nick Sabalausky wrote:"Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org> wrote in message news:i5mfji$2qtd$1 digitalmars.com...It's bound to break some code. AndreiI think it's a good enhancement. C++'s good old enum has been instrumental in finding a few bugs and clarifying a few interfaces in a project at work. Based on that experience I'd say that there's a chance more restrictive is better. We need to find a principled way to define semantics though - if we disable comparison it really means we're disabling implicit conversion."...it really means we're disabling implicit conversion" And that's a problem?
Sep 01 2010
Andrei:I think it's a good enhancement.Good :-)C++'s good old enum has been instrumental in finding a few bugs and clarifying a few interfaces in a project at work. Based on that experience I'd say that there's a chance more restrictive is better.There is also the experience of the C++0x group of designers, and their "enum class". One of the purpose of those "enum class" is to remove implicit conversions to int: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1719.pdfWe need to find a principled way to define semantics though - if we disable comparison it really means we're disabling implicit conversion.I agree. If bug bug 3999 gets accepted in the form I meant, then probably the bug 4261 too may be considered, because then enums aren't "ints" and the most natural way to print them on default is by name and not by hidden representation value: http://d.puremagic.com/issues/show_bug.cgi?id=4261It's bound to break some code.Yes, several of the about 25 entries of my 'short list' I have recently shown here are able to break some code. This is why I am showing them here now. I think of those bug reports are more "important" than the others I have put in Bugzilla because as more and more D2 code gets written, even tiny breaking changes become harder and harder to justify. Bye, bearophile
Sep 01 2010
On Wed, 01 Sep 2010 17:12:04 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 9/1/10 15:35 CDT, bearophile wrote:Does this mean no more defining bits as enums? enum myBits { flag1 = 1; flag2 = 2; flag3 = 4; } void fn(int flags); fn(myBits.flag1 | myBits.flag2); That was the one case where I really like the implicit conversion. -Steveso:I think it's a good enhancement. C++'s good old enum has been instrumental in finding a few bugs and clarifying a few interfaces in a project at work. Based on that experience I'd say that there's a chance more restrictive is better. We need to find a principled way to define semantics though - if we disable comparison it really means we're disabling implicit conversion.Another taste discussion?Nope. ----------------- Steven Schveighoffer:And I think if you have an idea to try and "fix" it, you might as well know now, it will never happen.<There I was explaining something better to Daniel Gibson. The purpose of the enhancement request 3999 has nothing to do with a request for a different keyword. ----------------- I think now I have presented my point as well as I can, and people have given comments and opinions. I'd like to Walter or/and Andrei to express their opinion about the bug 3999 :-)
Sep 02 2010
Does this mean no more defining bits as enums?Now that would be brutal, it is one of the best use cases of enum if not the best... -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Sep 02 2010
so wrote:Yes. I reckon, if an enum doesn't explicitly define the value of each member, it shouldn't implicitly convert to int -- and it should not be possible to treat it as bits. OTOH if each member has an explicitly defined value, it's reasonable to perform logical operations on it.Does this mean no more defining bits as enums?Now that would be brutal, it is one of the best use cases of enum if not the best...
Sep 02 2010
Don:OTOH if each member has an explicitly defined value, it's reasonable to perform logical operations on it.See my recent answer to Schveighoffer. I think that's not a fully good idea because when you define an enum like that and you use its values as powers-of-two flags, the type system doesn't help you enforce it is a true combination of the flags instead of a generic number (and you may put bugs when you define the values to assign to the flags), so I think something like a std.bitmanip.flagset that produces a struct is better when you need to define a flag set. Bye, bearophile
Sep 02 2010
"bearophile" <bearophileHUGS lycos.com> wrote in message news:i5p63u$2pl1$1 digitalmars.com...Don:I think all the discussions we've had about enum make it clear that enum suffers from a bit of an identity crisis. It doesn't know what it is and ends up being mediocre at everything it dabbles in.OTOH if each member has an explicitly defined value, it's reasonable to perform logical operations on it.See my recent answer to Schveighoffer. I think that's not a fully good idea because when you define an enum like that and you use its values as powers-of-two flags, the type system doesn't help you enforce it is a true combination of the flags instead of a generic number (and you may put bugs when you define the values to assign to the flags), so I think something like a std.bitmanip.flagset that produces a struct is better when you need to define a flag set.
Sep 02 2010
the type system doesn't help you enforce it is a true combination of the flags instead of a generic numberI have used std.bitmanip.bitfields some time, and in my opinion its best quality is its overflow tests. They have caught few of my bugs (it's easy to overflow such little numbers). It's also another good example why having runtime integer overflow tests is a Good Thing. Bye, bearophile
Sep 02 2010
bearophile wrote:Don:That's impossible. That would make interfacing to C a nightmare. By the way, enums which consist of flags frequently have values which have more than one bit set. The case { A=1, B=2, C=4, D=8 } is only a special case. In the general case, it's not realistic to hope that the compiler could determine which values are valid, and which are not. But, with my suggestion, simple enums (a list of mutually exclusive values) would become strong enums.OTOH if each member has an explicitly defined value, it's reasonable to perform logical operations on it.See my recent answer to Schveighoffer. I think that's not a fully good idea because when you define an enum like that and you use its values as powers-of-two flags, the type system doesn't help you enforce it is a true combination of the flags instead of a generic number (and you may put bugs when you define the values to assign to the flags), so I think something like a std.bitmanip.flagset that produces a struct is better when you need to define a flag set. Bye, bearophile
Sep 02 2010
I just stumbled upon this in std.typecons: http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#defineEnum Might be useful from some, I guess. On Fri, Sep 3, 2010 at 7:09 AM, Don <nospam nospam.com> wrote:
Sep 03 2010
Andrej Mitrovic:I just stumbled upon this in std.typecons: http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#defineEnum Might be useful from some, I guess.Thank you. I think std.typecons.defineEnum() may be removed. I don't think it's useful now. Bye, bearophile
Sep 03 2010
On 9/3/10 11:58 CDT, bearophile wrote:Andrej Mitrovic:Yah, that artifact predates the introspection means that make printing and parsing for enums possible. AndreiI just stumbled upon this in std.typecons: http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#defineEnum Might be useful from some, I guess.Thank you. I think std.typecons.defineEnum() may be removed. I don't think it's useful now. Bye, bearophile
Sep 03 2010
On Tue, 31 Aug 2010 20:59:15 -0400, bearophile <bearophileHUGS lycos.com> wrote:Daniel Gibson:AFAIK, enum meaning manifest constant was Andrei's request. And I think if you have an idea to try and "fix" it, you might as well know now, it will never happen. See this quote from Andrei in a bug report of mine (bug 1961): "And enum... you'll have to yank that out from my dead cold hands. Extending enum instead of adding yet another way of defining symbolic constants is The Right Thing to do. I am sure people would have realized how ridiculous the whole "manifest" thing is if we first proposed it. We just can't define one more way for each kind of snow there is." There was a point in D2 development with the 'manifest' keyword added to do exactly what enum now does (except for actual enumerations, for which enum was used). FWIW, I am not a huge fan of enum being used for meaning manifest constants that are not enumerations, but as far as daily usage, it's not really bad. It's somewhat of a petty problem, since enum is not functionally deficient. It just looks weird, especially to those used to other languages. I suppose you could think of it as an enumeration with one member :) -SteveThen there still is the consistency-issue (anon. enums are treated differently then named enums).Look at this:Se enum int n = 10; enum Color { Red, Green, Blue } Color color; if (color == Color.Red) { ... Color is a sequence of symbols, Red, Green and Blue, named Color. When you write your program often all you need to know is if color is Red or Green, and you don't care much how the compiler represents those symbols. The n is a compile-time constant value. It's not a sequence of something. Now, just for fun, replace the first enum with something as: ctconst int n = 10; enum Color { Red, Green, Blue } Color color; if (color == Color.Red) { ... ctconst is a fictional keyword that denotes compile-time constants. Now you are probably able to see that there is no correlation between the n and Color. In D they are using the same keyword by accident, probably because Walter thinks that saving a keyword is more important than keeping the semantics tidy.
Sep 01 2010
On Wednesday, September 01, 2010 12:36:04 Steven Schveighoffer wrote:AFAIK, enum meaning manifest constant was Andrei's request. And I think if you have an idea to try and "fix" it, you might as well know now, it will never happen. See this quote from Andrei in a bug report of mine (bug 1961): "And enum... you'll have to yank that out from my dead cold hands. Extending enum instead of adding yet another way of defining symbolic constants is The Right Thing to do. I am sure people would have realized how ridiculous the whole "manifest" thing is if we first proposed it. We just can't define one more way for each kind of snow there is." There was a point in D2 development with the 'manifest' keyword added to do exactly what enum now does (except for actual enumerations, for which enum was used). FWIW, I am not a huge fan of enum being used for meaning manifest constants that are not enumerations, but as far as daily usage, it's not really bad. It's somewhat of a petty problem, since enum is not functionally deficient. It just looks weird, especially to those used to other languages. I suppose you could think of it as an enumeration with one member :) -SteveIt's the kind of thing that is distasteful from a language purity standpoint, but it really doesn't cause any problems in code as far as I can tell. Once you know that you use enum to declare a manifest constant, it's perfectly normal to see it in code that way, so it's not confusing. And since you're not going to try to enumerate over such enums, it's not like they cause any real confusion with "normal" enums. You can think of it a bit like static. Static is used for different things in different contexts (even though most contexts are quite similar - IIRC, there's a way to define static in C++ which fits all of its uses in C++, though D adds some more that don't fit that definitition), but it doesn't really cause any confusion. enum is the same way. Sure, from the standpoint of language purity, manifest constants shouldn't be declared using enum, but the reality of the matter is that it works just fine. - Jonathan M Davis
Sep 01 2010
"Jonathan M Davis" <jmdavisprog gmail.com> wrote in message news:mailman.38.1283370572.858.digitalmars-d puremagic.com...You can think of it a bit like static. Static is used for different things in different contexts (even though most contexts are quite similar - IIRC, there's a way to define static in C++ which fits all of its uses in C++, though D adds some more that don't fit that definitition), but it doesn't really cause any confusion. enum is the same way. Sure, from the standpoint of language purity, manifest constants shouldn't be declared using enum, but the reality of the matter is that it works just fine.Static is a little bit better in that the uses of it at least have some connection to the dictionary meaning of "static", even if perhaps a little distant. But there's just no way to stretch the dictionary meaning of "enumeration" to include manifest constants. Like everyone else, I can at least live with it, but I look forward to the day the linker issue is fixed so we can finally mutilate/destroy/kill it, dead, dead, dead with extreme prejudice in favor of immutable. It's a stain - doesn't really cause a problem, but boy is it ever UGLY.
Sep 01 2010
Static is a little bit better in that the uses of it at least have some connection to the dictionary meaning of "static", even if perhaps a little distant. But there's just no way to stretch the dictionary meaning of "enumeration" to include manifest constants. Like everyone else, I can at least live with it, but I look forward to the day the linker issue is fixed so we can finally mutilate/destroy/kill it, dead, dead, dead with extreme prejudice in favor of immutable. It's a stain - doesn't really cause a problem, but boy is it ever UGLY.Float is not floating and double is not doubling, are they next? -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Sep 01 2010
"so" <so so.do> wrote in message news:op.videg00w7dtt59 so-pc...Float (short for "floating point"): The decimal point can "float" around as the value changes (not a literal use of "float", but there's nothing wrong with metaphoric uses of words, even in ordinary speech). This type is named in contrast to the fixed-point arithmetic that was often used as an old-school optimization (where the decimal point was always at a fixed location, for example, the high 16-bits may have been the whole-number part, and the low 16-bits may have been the decimal part). Double: This one's easy: It's double the size of a float.Static is a little bit better in that the uses of it at least have some connection to the dictionary meaning of "static", even if perhaps a little distant. But there's just no way to stretch the dictionary meaning of "enumeration" to include manifest constants. Like everyone else, I can at least live with it, but I look forward to the day the linker issue is fixed so we can finally mutilate/destroy/kill it, dead, dead, dead with extreme prejudice in favor of immutable. It's a stain - doesn't really cause a problem, but boy is it ever UGLY.Float is not floating and double is not doubling, are they next?
Sep 01 2010
Float (short for "floating point"): The decimal point can "float" around as the value changes (not a literal use of "float", but there's nothing wrong with metaphoric uses of words, even in ordinary speech). This type is named in contrast to the fixed-point arithmetic that was often used as an old-school optimization (where the decimal point was always at a fixed location, for example, the high 16-bits may have been the whole-number part, and the low 16-bits may have been the decimal part). Double: This one's easy: It's double the size of a float.I know what they are, but at the same time was expecting you to get the point :) When you need a compile-time type in C/C++ mostly you don't need a type, just : enum { value = 10 }; // Also, this is suggested over const Coming from C/C++ enum constants are pretty straightforward as compile-time constants. And please, it is only 4 letters. (In case you missed, they are e, n, u, m. They are the 4 best looking characters on every editor!) This reminds me the "retro" case, where most argue against and making up names such like reverseAndSomeOtherUglyNonsense. Anyone here got trouble understanding what "enum" is and what it does? No, It wasn't the case in retro either. -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Sep 01 2010
Float (short for "floating point"): The decimal point can "float" around as the value changes (not a literal use of "float", but there's nothing wrong with metaphoric uses of words, even in ordinary speech). This type is named in contrast to the fixed-point arithmetic that was often used as an old-school optimization (where the decimal point was always at a fixed location, for example, the high 16-bits may have been the whole-number part, and the low 16-bits may have been the decimal part). Double: This one's easy: It's double the size of a float.If you throw "2.7f" on a water, does it float or you need to multiply with pi first? Why don't we change double to hmm... doubleTheSizeOfFloat? Lets test it! - manifest doubleTheSizeOfFloat pi=3.14; doubleTheSizeOfFloat f=2.7; if(!floats(f)) multiplyFirstOneWithTheSecondAndAssignToTheFirstParameter(f, pi); // that was the java operator overloading case? Yeh fundamental type but still it is funny! - enum pi=3.14; double f=2.7; if(!floats(f)) f *= pi; -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Sep 01 2010
"so" <so so.do> wrote in message news:op.vidgxic47dtt59 so-pc...Like I said, "metaphor". By contrast there's no basis for a metaphor between "enumeration" and manifest constants.Float (short for "floating point"): The decimal point can "float" around as the value changes (not a literal use of "float", but there's nothing wrong with metaphoric uses of words, even in ordinary speech). This type is named in contrast to the fixed-point arithmetic that was often used as an old-school optimization (where the decimal point was always at a fixed location, for example, the high 16-bits may have been the whole-number part, and the low 16-bits may have been the decimal part). Double: This one's easy: It's double the size of a float.If you throw "2.7f" on a water, does it float or you need to multiply with pi first?Why don't we change double to hmm... doubleTheSizeOfFloat? Lets test it!Please don't go using strawmen. No one ever said anything about abbreviations being bad.
Sep 01 2010
"Daniel Gibson" <metalcaedes gmail.com> wrote in message news:mailman.26.1283301521.858.digitalmars-d puremagic.com...Then there still is the consistency-issue (anon. enums are treated differently then named enums).Anon. enums *are* fundamentally different from named enums. It's already inconsistent.
Aug 31 2010
bearophile Wrote:But enums are not integers?? Where did you get it?
Sep 01 2010
Kagamin:The whole point of this discussion about my enhancement request 3999 is to turn a certain subset of enums into "not integers" (or "not bytes", "not longs", etc). Bye, bearophileBut enums are not integers?? Where did you get it?
Sep 01 2010
On Wednesday, September 01, 2010 13:53:51 Andrej Mitrovic wrote:I thought to!string(Enum) already does this? This was the example I posted in bug report 4261: import std.conv : to; import std.stdio: writeln; void main() { enum Foo { Zero, One } Foo f = Foo.One; writeln(to!string(f)); } Prints: OneWell, like I said, it never occurred to me that you even could print enums as strings in D, so I don't know how it's typically done. However, if it's as simple as that, I don't really see what the problem is. Sure, it would be nice if they printed as strings by default rather than the generally useless base type of int or whatever, but using to!string like that is quite straightforward. - Jonathan M Davis
Sep 01 2010
Steven Schveighoffer:enum myBits { flag1 = 1; flag2 = 2; flag3 = 4; } void fn(int flags); fn(myBits.flag1 | myBits.flag2); That was the one case where I really like the implicit conversion.Thank you for that important use case. enum is used for three different things: compile-time constants, a sequence of separated symbols, and a group of flags that may be grouped. flags, and documents that an enum is indeed a flags set. Recently I have proposed to add to Phobos something similar to a std.bitmanip.bitfields that builds a flag set (the powers of two are set automatically, you just give the flag names. It may also add a first dummy flag with value zero). Probably it's not too much hard to do. The problem is that such (hypotetically named) std.bitmanip.flagset defines what the language/compiler sees as a normal enum, so it has to share its features with normal enums. In C++0x you don't have this problem, because you use "enum" to define flags and "enum class" to define the strongly typed sequence of symbols. Your fn() function doesn't truly accept any int, it accepts only a bitwise combination of members of myBits. A more strict type system may enforce this. This is feasible in D if std.bitmanip.flagset returns a struct instead of an enum. This struct contains just an int and methods to perform bitwise operations that return a struct of the same type. So the signature becomes void fn(MyBits flags). This is an idea: struct MyBits { private alias size_t T; static assert(is(T == ubyte) || is(T == ushort) || is(T == uint) || is(T == ulong) || is(T == size_t)); private T _bits; public enum nothing = MyBits(0); private enum uint nflags = 3; // flag1, flag2, flag3 static assert(nflags <= T.sizeof * 8); static if (nflags == (T.sizeof * 8)) private enum T full = T.max; // because ((1UL << 64) - 1) != ulong.max else private enum T full = ((cast(T)1) << nflags) - 1; public enum flag1 = MyBits((cast(T)1) << 0); public enum flag2 = MyBits((cast(T)1) << 1); public enum flag3 = MyBits((cast(T)1) << 2); this(MyBits other) { this._bits = other._bits; } this(T value) { this._bits = value; } invariant() { assert(!(this._bits & ~full)); } MyBits opUnary(string Op="~")() { return MyBits(~this._bits & full); } MyBits opBinary(string op)(MyBits other) if (op == "|" || op == "&") { mixin("return MyBits(this._bits " ~ op ~" other._bits);"); } } //-------------------------- import std.stdio: writeln; void fn(MyBits flags) { writeln(flags._bits); } void main() { fn(MyBits.flag1 | MyBits.flag2); fn(MyBits.flag1 & MyBits.flag2); auto f = MyBits.flag1; assert(f == MyBits.flag1); writeln((1UL << 64) - 1); } Given the names "flag1", "flag2", "flag3" (and the optional type T), std.bitmanip.flagset generates a struct like MyBits (plus few more missing parts). ------------------------- Don:OTOH if each member has an explicitly defined value, it's reasonable to perform logical operations on it.Thank you for your usually wise point of view. Bye, bearophile
Sep 02 2010
Don:That's impossible. That would make interfacing to C a nightmare.I see.By the way, enums which consist of flags frequently have values which have more than one bit set. The case { A=1, B=2, C=4, D=8 } is only a special case.That indeed happens, but from the code that I have seen the most common case is the one with powers of two flags. This is why I think it's useful to add the flagset struct to Phobos, because it avoids/catches some common bugs.In the general case, it's not realistic to hope that the compiler could determine which values are valid, and which are not.Right. But a flagset helps because: - It gives a very short definition syntax for the common case when flags are power of two. - In that case it removes the mistakes in power-of-two flag and the missing dummy (0) flag. - The struct invariant is able to catch few runtime bugs because it tests that the unused bits in the underlying value are always zero.But, with my suggestion, simple enums (a list of mutually exclusive values) would become strong enums.This is better than the current situation. I'd like Walter to give a word on this thread. Bye, bearophile
Sep 05 2010