www.digitalmars.com         C & C++   DMDScript  

D - Enums, Flags, Constants

reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Two suggestions:

1) Allow multiple enums with the same name; determine which is
appropriate based on context (what they are being used for):
    enum {  SUCCESS, FAIL } foo;  // SUCCESS=0, FAIL=1
    enum {  FAIL, SUCCESS } bar;  // FAIL=0,SUCCESS=1
    foo f = SUCCESS;
    bar b = SUCCESS;
    int i = f;    // i = 0
    int j = b;    // i = 1
I know it's not C-like...but it means that you can mix libraries with
similar declarations with no problems.  Otherwise SUCCESS has to be
defined as MYAPI_SUCCESS to ensure that there's no conflict.

2) Allow a new keyword, 'flags' that is exactly like an enum except that
the default assigned values are bitflags.  The default first value is
0x01; the next assigned flag is found by taking the first unused bit:
    flag {
        RED,        // 0x01
        BLUE,        // 0x02
        RED_BLUE = RED | BLUE,    // 0x03
        GREEN,        // 0x04  (this is the first unused bit)
        BLACK = 0,    // 0x00
        WHITE = ~BLACK
    }

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Feb 14 2002
next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6C3AC0.4F438635 deming-os.org...
 Two suggestions:

 1) Allow multiple enums with the same name; determine which is
 appropriate based on context (what they are being used for):
     enum {  SUCCESS, FAIL } foo;  // SUCCESS=0, FAIL=1
     enum {  FAIL, SUCCESS } bar;  // FAIL=0,SUCCESS=1
     foo f = SUCCESS;
     bar b = SUCCESS;
     int i = f;    // i = 0
     int j = b;    // i = 1
 I know it's not C-like...but it means that you can mix libraries with
 similar declarations with no problems.  Otherwise SUCCESS has to be
 defined as MYAPI_SUCCESS to ensure that there's no conflict.

With the import module system, whenever there's an ambiguity, it can be resolved by prefixing the name with the module name, like: myabi.SUCCESS
 2) Allow a new keyword, 'flags' that is exactly like an enum except that
 the default assigned values are bitflags.  The default first value is
 0x01; the next assigned flag is found by taking the first unused bit:
     flag {
         RED,        // 0x01
         BLUE,        // 0x02
         RED_BLUE = RED | BLUE,    // 0x03
         GREEN,        // 0x04  (this is the first unused bit)
         BLACK = 0,    // 0x00
         WHITE = ~BLACK
     }

You can use: enum flag { RED = 0x01, BLUE = 0x02, RED_BLUE = RED | BLUE, GREEN = 0x04, // (this is the first unused bit) BLACK = 0, WHITE = ~BLACK, } now.
Feb 14 2002
next sibling parent reply Russell Borogove <kaleja estarcion.com> writes:
Walter wrote:
 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3C6C3AC0.4F438635 deming-os.org...
2) Allow a new keyword, 'flags' that is exactly like an enum except that
the default assigned values are bitflags.  The default first value is
0x01; the next assigned flag is found by taking the first unused bit:
    flag {
        RED,        // 0x01
        BLUE,        // 0x02
        RED_BLUE = RED | BLUE,    // 0x03
        GREEN,        // 0x04  (this is the first unused bit)
        BLACK = 0,    // 0x00
        WHITE = ~BLACK
    }

You can use: enum flag { RED = 0x01, BLUE = 0x02, RED_BLUE = RED | BLUE, GREEN = 0x04, // (this is the first unused bit) BLACK = 0, WHITE = ~BLACK, } now.

Yup, and when you start adding new elements with careless cut-n-paste when you're short of sleep, you wind up with two different flags using the 0x200 bit and then bad things happen and you cry. The automatic bit-using behavior that Russ Lewis suggests would avoid that problem neatly. You can just tell us to get more sleep, of course.... -RB
Feb 14 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russell Borogove" <kaleja estarcion.com> wrote in message
news:3C6C7043.3060402 estarcion.com...

 You can just tell us to get more sleep, of course....

... but the appropriate features (to help the programmer to sleep for at least 8 hours) should be added to D then...
Feb 14 2002
parent Russell Borogove <kaleja estarcion.com> writes:
Pavel Minayev wrote:
 "Russell Borogove" <kaleja estarcion.com> wrote in message
 news:3C6C7043.3060402 estarcion.com...
 
 
You can just tell us to get more sleep, of course....

... but the appropriate features (to help the programmer to sleep for at least 8 hours) should be added to D then...

Right -- and to get that kind of sleep, we need fewer errors in our code and more peace of mind, so either way the "flags" version of enum should be available. -RB
Feb 15 2002
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:

 With the import module system, whenever there's an ambiguity, it can be
 resolved by prefixing the name with the module name, like:
     myabi.SUCCESS

Right! This is a Good Thing, and is a substantial upgrade over C++. However, my primary desire was not to be able to resolve ambiguities, but to reduce unnecessary typing. I would prefer that the user not even have to consider dealing with ambiguities when context could resolve them. This is especially true if you were using just one of the modules...and had typed all your code using "SUCCESS". Then you add an import to your code, and suddenly you have "ambiguous symbol" popping up all over your code. That would make me frown, to have to do a search & replace all over my code.. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 15 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6D2C25.71BE05C2 deming-os.org...
 However, my primary desire was not to be able to resolve ambiguities, but

 reduce unnecessary typing.  I would prefer that the user not even have to
 consider dealing with ambiguities when context could resolve them.

In most cases, there won't be any ambiguity, and you won't need to put the module qualifier on.
 This is especially true if you were using just one of the modules...and

 typed all your code using "SUCCESS".  Then you add an import to your code,

 suddenly you have "ambiguous symbol" popping up all over your code.  That
 would make me frown, to have to do a search & replace all over my code..

It's not that bad <g>.
Feb 15 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4jfd4$1rar$2 digitaldaemon.com...

 This is especially true if you were using just one of the modules...and

 typed all your code using "SUCCESS".  Then you add an import to your


 and
 suddenly you have "ambiguous symbol" popping up all over your code.


 would make me frown, to have to do a search & replace all over my code..

It's not that bad <g>.

Still... why not an override attribute for import directive? import foo, bar; // normal import: any conflicts have to be // disambiguated explicitly override import baz; // all identifiers in baz override those in // foo and bar with the same name Identifiers could also be overriden twice or more: import foo; // contains Foo override import bar; // contains Foo; overrides foo.Foo override import baz; // contains Foo; overrides bar.Foo Whaddya think?
Feb 15 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel Minayev wrote:

 Still... why not an override attribute for import directive?

     import foo, bar;      // normal import: any conflicts have to be
                           // disambiguated explicitly

     override import baz;  // all identifiers in baz override those in
                           // foo and bar with the same name

 Identifiers could also be overriden twice or more:

     import foo;            // contains Foo
     override import bar;   // contains Foo; overrides foo.Foo
     override import baz;   // contains Foo; overrides bar.Foo

 Whaddya think?

For the stuff I'm talking about, that would be far WORSE than anything else. What if foo (which you wrote lots of code for) defined SUCCESS as 1, while bar or baz defined it as 0? Then all your "return SUCCESS" would actually be doing "return FAIL". I'd prefer the ambiguity :( -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Feb 15 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6D6E43.F7626219 deming-os.org...

 For the stuff I'm talking about, that would be far WORSE than anything

 What if foo (which you wrote lots of code for) defined SUCCESS as 1, while

 or baz defined it as 0?  Then all your "return SUCCESS" would actually be

 "return FAIL".  I'd prefer the ambiguity :(

For this reason, named enums should be used: enum Foo { Success, Failure } enum Bar { Failure, Success } ... foo = Foo.Success; bar = Bar.Success; The generic idea of one modules overriding other is better applied to functions and classes, and was discussed earlier... I just thought I'd raise the point once again =) Oh, BTW, Walter, what about private imports?
Feb 15 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
 Oh, BTW, Walter, what about private imports?

I'm focussed on the inline assembler <g>.
Feb 17 2002
next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:a4pp99$1ek3$1 digitaldaemon.com...

 I'm focussed on the inline assembler <g>.

GREAT!
Feb 17 2002
prev sibling parent "Carlos Santander B." <carlos8294 msn.com> writes:
"Walter" <walter digitalmars.com> escribiσ en el mensaje
news:a4pp99$1ek3$1 digitaldaemon.com...
|
| "Pavel Minayev" <evilone omen.ru> wrote in message
| > Oh, BTW, Walter, what about private imports?
|
| I'm focussed on the inline assembler <g>.
|
|
|

Inline assembler is already implemented, isn't it? :D

I mean, if I had:

------a.d
class A {}
------b.d
private import a;  /*1*/
class B:A {}
------c.d
import b;
B _b;
A _a; /*2*/

Because of /*1*/, I don't want /*2*/ to work. But it does.

—————————————————————————
Carlos Santander


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.463 / Virus Database: 262 - Release Date: 2003-03-17
Mar 22 2003
prev sibling next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6C3AC0.4F438635 deming-os.org...
 Two suggestions:

 1) Allow multiple enums with the same name; determine which is
 appropriate based on context (what they are being used for):
     enum {  SUCCESS, FAIL } foo;  // SUCCESS=0, FAIL=1
     enum {  FAIL, SUCCESS } bar;  // FAIL=0,SUCCESS=1
     foo f = SUCCESS;
     bar b = SUCCESS;
     int i = f;    // i = 0
     int j = b;    // i = 1
 I know it's not C-like...but it means that you can mix libraries with
 similar declarations with no problems.  Otherwise SUCCESS has to be
 defined as MYAPI_SUCCESS to ensure that there's no conflict.

You forget about the fact that each named enum has its own namespace. So your example should look like this in D (also note the difference in syntax =)): enum foo { SUCCESS, FAIL } enum bar { FAIL, SUCCESS } foo f = foo.SUCCESS; bar b = bar.SUCCESS; ... So it is impossible to get a name clash. This also makes it unnecessary to prefix enum members with some kind of "enum namespace tag": enum Border { None, Single, Sizeable, Dialog, ToolWin, SizeToolWin } Even if you get a variable named Single, the name clash still doesn't happen. A cool feature I must say!
 2) Allow a new keyword, 'flags' that is exactly like an enum except that
 the default assigned values are bitflags.  The default first value is
 0x01; the next assigned flag is found by taking the first unused bit:
     flag {
         RED,        // 0x01
         BLUE,        // 0x02
         RED_BLUE = RED | BLUE,    // 0x03
         GREEN,        // 0x04  (this is the first unused bit)
         BLACK = 0,    // 0x00
         WHITE = ~BLACK
     }

This is a good idea, IMO. Great when you have something like 20 flags, and it's soooo easy to make a mistake while typing, say mistype 0x80 for 0x90, and then you can't understand why your program doesn't work...
Feb 14 2002
parent reply "Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4i4ge$1826$1 digitaldaemon.com...

 You forget about the fact that each named enum has its own namespace.
 So your example should look like this in D (also note the difference
 in syntax =)):

     enum foo { SUCCESS, FAIL }
     enum bar { FAIL, SUCCESS }
     foo f = foo.SUCCESS;
     bar b = bar.SUCCESS;
     ...

 So it is impossible to get a name clash.

Is this so? Is there no way to use it without the prefix?
 A cool feature I must say!

I'm not sure I like it.
 2) Allow a new keyword, 'flags' that is exactly like an enum except that
 the default assigned values are bitflags.  The default first value is
 0x01; the next assigned flag is found by taking the first unused bit:
     flag {
         RED,        // 0x01
         BLUE,        // 0x02
         RED_BLUE = RED | BLUE,    // 0x03
         GREEN,        // 0x04  (this is the first unused bit)
         BLACK = 0,    // 0x00
         WHITE = ~BLACK
     }

This is a good idea, IMO. Great when you have something like 20 flags, and it's soooo easy to make a mistake while typing, say mistype 0x80 for 0x90, and then you can't understand why your program doesn't work...

Not only that. I don't know what D does, but in C++, if you want to combine bits from an enum and assign it to a variable of the enum type, you need to do an explicit cast. For example: enum Speech { Blah, // 0x01 Yadda, // 0x02 Mumble, // 0x04 }; Speech mySpeech1 = Blah | Yadda; // Doesn't work! Speech mySpeech2 = Speech(Blah | Yadda); // Works Salutaciones, JCAB http://www.JCABs-Rumblings.com
Feb 14 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message
news:a4i7lv$19dn$1 digitaldaemon.com...

    Is this so? Is there no way to use it without the prefix?

Yes. But you can use something like: enum { red, green, blue } alias int Color;
    Not only that. I don't know what D does, but in C++, if you want to
 combine bits from an enum and assign it to a variable of the enum type,

 need to do an explicit cast. For example:

 enum Speech {
   Blah,   // 0x01
   Yadda,  // 0x02
   Mumble, // 0x04
 };

 Speech mySpeech1 = Blah | Yadda; // Doesn't work!
 Speech mySpeech2 = Speech(Blah | Yadda); // Works

It is so in D as well. So, the flags construct should support this... know what it reminds me of? Pascal set-types! It'd be great to have these in D: set Speech { Blah, Yadda, Mumble } ... Speech speech; speech = Speech[Blah, Yadda]; ... if (speech.Blah) { speech += Speech.Mumble; speech -= Speech.Blah; } ... speech -= Speech[Yadda, Mumble]; Well you get the idea. Internally the set is represented by an int bitfield. You can initialize it, add or remove (or set and reset in other interpretation) elements, add, subtract and multiply sets: set Color { Red, Green, Blue } ... foo = Color[Red, Green]; bar = Color[Green, Blue]; ... baz = foo + bar; // baz is now Color[Red, Green, Blue] baz = foo - bar; // baz is now Color[Red] baz = foo * bar; // baz is now Color[Green]
Feb 15 2002
prev sibling next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
It would also be useful (for some code I have) to be able to define a
certain subset of integers that *could* be implicitly cast to the enum
type.  Specifically, 0 is a special case for many functions that take enums
as parameters, and IMHO '0' is a better identifier than "ENUM_TYPE_DEFAULT".

    enum foo {
        0,                    // a constant 0 can be implicitly cast to foo
        RUNNING,      // defined to be 1
        IDLE                // defined to be 2
    }

Maybe this is too crazy...I could just defined DEFAULT=0.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Feb 15 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6D637D.6C18BF32 deming-os.org...

 It would also be useful (for some code I have) to be able to define a
 certain subset of integers that *could* be implicitly cast to the enum
 type.  Specifically, 0 is a special case for many functions that take

 as parameters, and IMHO '0' is a better identifier than

     enum foo {
         0,                    // a constant 0 can be implicitly cast to

         RUNNING,      // defined to be 1
         IDLE                // defined to be 2
     }

Then maybe it's better for "null" to be implicitly castable to any enum type?
Feb 15 2002
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Good idea!  Any other viewpoints?

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Feb 15 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6D6E57.B365408B deming-os.org...

 Good idea!  Any other viewpoints?

Yes, one =) enum Foo { whatever, Running, Idle } ... foo = Foo.min; min is a standard property for any enum... it's not always 0 so you have to ensure that minimal member is zero. Also, using null for enums might be not a good idea (since it's already used with pointers). What about "default"? // default can be a separate member... enum Foo { default = 0, Running, Idle } ... Foo foo; foo = default; // .. or one of existing members can be default enum Bar { default Running = 0, Idle } ... Bar bar bar = default; // could be Bar.Running
Feb 15 2002
prev sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6C3AC0.4F438635 deming-os.org...
 Two suggestions:

 2) Allow a new keyword, 'flags' that is exactly like an enum except that
 the default assigned values are bitflags.  The default first value is
 0x01; the next assigned flag is found by taking the first unused bit:
     flag {
         RED,        // 0x01
         BLUE,        // 0x02
         RED_BLUE = RED | BLUE,    // 0x03
         GREEN,        // 0x04  (this is the first unused bit)
         BLACK = 0,    // 0x00
         WHITE = ~BLACK
     }

YES! Although bitfields can accomplish about the same thing as flags, and can be cleaner, although they rely heavily on the compiler to optimize them back to flags. Also if this flag thing is introduced, the type defined by it should accept any union of the individual flag members, such as: flag Colors { RED,BLUE,GREEN, } Colors acolor = RED|GREEN; // NO CAST NEEDED -- result of OR'ing two members of // flag Colors is another value of type Colors, NOT an int. Sean
Feb 15 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:a4ktv4$2fbs$1 digitaldaemon.com...

 YES!  Although bitfields can accomplish about the same thing as flags, and
 can be cleaner, although they rely heavily on the compiler to optimize

 back to flags.

Especially since D has no bitfields =) Only arrays of bits, which is not the same...
 Also if this flag thing is introduced, the type defined by it should

 any union of the individual flag members, such as:

 flag Colors
 {
   RED,BLUE,GREEN,
 }

 Colors acolor = RED|GREEN;   // NO CAST NEEDED -- result of OR'ing two
 members of
                                                 // flag Colors is another
 value of type Colors, NOT an int.

I propose to use operator + for this purpose. It makes more clear that colors are Red AND (PLUS) Green. Also, to disambiguate the declarations, you would either use the qualifier: color = Color.RED + Color.GREEN; ...or a "flags constructor": color = Color[RED, GREEN];
Feb 16 2002
parent reply Russell Borogove <kaleja estarcion.com> writes:
Pavel Minayev wrote:
 "Sean L. Palmer" <spalmer iname.com> wrote in message
 news:a4ktv4$2fbs$1 digitaldaemon.com...
 
Also if this flag thing is introduced, the type defined by it should
accept 
any union of the individual flag members, such as:

flag Colors
{
  RED,BLUE,GREEN,
}

Colors acolor = RED|GREEN;   // NO CAST NEEDED -- result of OR'ing two
members of
                                                // flag Colors is another
value of type Colors, NOT an int.


YES!
 I propose to use operator + for this purpose. It makes more clear
 that colors are Red AND (PLUS) Green. 

I'd prefer that both | and + be available, and retain the distinct meanings they have for ints. In the colors example, if MAGENTA is defined as either RED+BLUE or RED|BLUE, there's a useful semantic difference between MAGENTA+BLUE and MAGENTA|BLUE (especially when you get away from constants and into variables). Generations of us filthy unwashed C fanatics have learned this weird distinction, and IMO it would be Evil and Rude to suddenly make + do a bitwise OR. You and your project team, of course, Pavel, are more than welcome to define a "class Color" which overloads the plus sign to do a bitwise OR. Or perhaps a bitwise AND. Whatever. -RB
Feb 16 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russell Borogove" <kaleja estarcion.com> wrote in message
news:3C6F577B.4030803 estarcion.com...

 I'd prefer that both | and + be available, and retain the
 distinct meanings they have for ints. In the colors example,
 if MAGENTA is defined as either RED+BLUE or RED|BLUE, there's
 a useful semantic difference between MAGENTA+BLUE and
 MAGENTA|BLUE (especially when you get away from constants
 and into variables). Generations of us filthy unwashed C
 fanatics have learned this weird distinction, and IMO it
 would be Evil and Rude to suddenly make + do a bitwise OR.

It's not a bitwise OR, it's a union operator. Just forget about flags as a set of bits, implementation is of compiler's business only. Think of it just as of set of flags where each can be set or reset. a + b means unionize, so the result will have all flags from a set, as well as all flags from b. Since you cannot set the same flag twice, it is simply set once. Internally, this is of course implemented by the bitwise OR operator. But we shouldn't care about such things. BTW if flags aren't integers (at least not implicitly castable), usual arithmetic + has no meaning on them. Nobody uses + to construct flagsets out of distinct flags because it is unsafe. You use | anyhow. Making + a synonym for it shouldn't hurt... The same would apply to -. a - b results in all flags from a set except of those that were set in b. In C you'd write it as a & ~b. I claim that a - b is easier to read and understand here...
 You and your project team, of course, Pavel, are more than
 welcome to define a "class Color" which overloads the plus
 sign to do a bitwise OR. Or perhaps a bitwise AND. Whatever.

This doesn't only apply to colors. This applies to any flag sets. What's the reason of adding a bitset to a bitset anyhow? You won't get any useful result, nothing of real interest...
Feb 17 2002
parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4nsf4$ob3$1 digitaldaemon.com...
 "Russell Borogove" <kaleja estarcion.com> wrote in message
 news:3C6F577B.4030803 estarcion.com...

 I'd prefer that both | and + be available, and retain the
 distinct meanings they have for ints. In the colors example,
 if MAGENTA is defined as either RED+BLUE or RED|BLUE, there's
 a useful semantic difference between MAGENTA+BLUE and
 MAGENTA|BLUE (especially when you get away from constants
 and into variables). Generations of us filthy unwashed C
 fanatics have learned this weird distinction, and IMO it
 would be Evil and Rude to suddenly make + do a bitwise OR.

It's not a bitwise OR, it's a union operator. Just forget about flags as a set of bits, implementation is of compiler's business only. Think of it just as of set of flags where each can be set or reset. a + b means unionize, so the result will have all flags from a set, as well as all flags from b. Since you cannot set the same flag twice, it is simply set once. Internally, this is of course implemented by the bitwise OR operator. But we shouldn't care about such things. BTW if flags aren't integers (at least not implicitly castable), usual arithmetic + has no meaning on them. Nobody uses + to construct flagsets out of distinct flags because it is unsafe. You use | anyhow. Making + a synonym for it shouldn't hurt... The same would apply to -. a - b results in all flags from a set except of those that were set in b. In C you'd write it as a & ~b. I claim that a - b is easier to read and understand here...
 You and your project team, of course, Pavel, are more than
 welcome to define a "class Color" which overloads the plus
 sign to do a bitwise OR. Or perhaps a bitwise AND. Whatever.

This doesn't only apply to colors. This applies to any flag sets. What's the reason of adding a bitset to a bitset anyhow? You won't get any useful result, nothing of real interest...

I really like this flag idea, but isn't it just a subset of Pascal sets? Here is what it could look like in D style notation: enum EColors {RED, GREEN, BLUE}; set[EColors] SColorFlags; SColorFlags = [RED, GREEN]; SColorFlags -= RED; SColorFlags += BLUE; if (BLUE in SColorFlags) something like that? Then you could also make sets of characters, a very usefull feature in Pascal IMHO: set[char] SCharSet; SCharSet scValidPasswordChars = ['a'..'z', 'A'..'Z', '_', '-', '0'..'9']; if (cTypedChar in scValidPasswordChars) I always missed sets in C/C++... -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 18 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a4rlaa$27ug$1 digitaldaemon.com...

 I really like this flag idea, but isn't it just a subset of Pascal sets?

Absolutely, I've mentioned this already, and I suggested using the keyword "set" for this";
 Here is what it could look like in D style notation:

 enum EColors {RED, GREEN, BLUE};
 set[EColors] SColorFlags;

Maybe it's better to make sets separate types, like structs or enums? set EColors {RED, GREEN, BLUE} -- or -- enum EColor {RED, GREEN, BLUE} set EColors: EColor; ... EColors colors;
 SColorFlags = [RED, GREEN];

First of all, don't forget that each enum/set has its own namespace. So you use EColor.RED and EColor.BLUE, not just RED or BLUE. Then, to simplify things for the compiler, and to distinguish from awaited array literals, some form of "set constructor" could be used: colors = EColors[RED, GREEN]; // the same as above... colors = EColors.RED + EColors.GREEN;
 SColorFlags -= RED;
 SColorFlags += BLUE;
 if (BLUE in SColorFlags)

I propose SColorFlags.BLUE - this is not Pascal, so it's better to follow the C/D notation here, IMO.
 something like that?
 Then you could also make sets of characters, a very usefull feature
 in Pascal IMHO:

 set[char] SCharSet;
 SCharSet scValidPasswordChars = ['a'..'z', 'A'..'Z', '_', '-', '0'..'9'];
 if (cTypedChar in scValidPasswordChars)

Ugh... this means sets should support ranges and stuff... something I think would be too huge to ask Walter for. I'd be pretty happy with sets as "bit flags".
Feb 18 2002
parent reply "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4rmpd$28jn$1 digitaldaemon.com...
 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:a4rlaa$27ug$1 digitaldaemon.com...

 I really like this flag idea, but isn't it just a subset of Pascal sets?

Absolutely, I've mentioned this already, and I suggested using the keyword "set" for this";
 Here is what it could look like in D style notation:

 enum EColors {RED, GREEN, BLUE};
 set[EColors] SColorFlags;

Maybe it's better to make sets separate types, like structs or enums? set EColors {RED, GREEN, BLUE}

What about a set of chars... set SChars {'a', 'b', 'c', Aaargh :)
     -- or --

     enum EColor {RED, GREEN, BLUE}
     set EColors: EColor;

Would work ok
     ...
     EColors colors;

 SColorFlags = [RED, GREEN];

First of all, don't forget that each enum/set has its own namespace. So you use EColor.RED and EColor.BLUE, not just RED or BLUE.

Autch....I don't know if I like that...Although it has some great advantages...But I thought prepending the namespace was only necessary if there could be ambiguity?
 Then, to simplify things for the compiler, and to distinguish from
 awaited array literals, some form of "set constructor" could be
 used:

     colors = EColors[RED, GREEN];
     // the same as above...
     colors = EColors.RED + EColors.GREEN;

Ok
 SColorFlags -= RED;
 SColorFlags += BLUE;
 if (BLUE in SColorFlags)

I propose SColorFlags.BLUE - this is not Pascal, so it's better to follow the C/D notation here, IMO.

Could you explain some more? Would you mean that if (SColorFlags.BLUE) would be the same as if (BLUE in SColorFlags) in Pascal?
 something like that?
 Then you could also make sets of characters, a very usefull feature
 in Pascal IMHO:

 set[char] SCharSet;
 SCharSet scValidPasswordChars = ['a'..'z', 'A'..'Z', '_', '-',


 if (cTypedChar in scValidPasswordChars)

Ugh... this means sets should support ranges and stuff... something I think would be too huge to ask Walter for. I'd be pretty happy with sets as "bit flags".

It's a lot to ask, okay, but it also offers some great advantages. I would be okay with bit flags too though, but I would then call them flags to avoid confusion with pascal. Whichever way you put it, I think a way to define flags would be a great benefit, because they are used *very* often! -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 19 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a4u115$8h1$1 digitaldaemon.com...

 What about a set of chars...
 set SChars {'a', 'b', 'c', Aaargh :)

For simplicity, it'd be better for sets to fit into 32 bits, I believe. But if they don't, then... set SChars { a = 'a', b, c , ... }
Feb 19 2002
parent reply "Sean L. Palmer" <spalmer iname.com> writes:
Some architectures out there have 128 bit registers... wouldn't want them to
feel overpowered would we?  ;)  Besides, you can just continue chaining
together registers until you have enough bits... they are flags after all,
there's no carry to worry about;  It's not nearly as complicated as, say,
long division.  So I wouldn't advise imposing an absolute limit.  Pascal
sets had a limit of 256 bits and that wasn't enough from what I remember
trying to use it for sometimes.

Sean

"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4u1cf$8o8$1 digitaldaemon.com...
 "OddesE" <OddesE_XYZ hotmail.com> wrote in message
 news:a4u115$8h1$1 digitaldaemon.com...

 What about a set of chars...
 set SChars {'a', 'b', 'c', Aaargh :)

For simplicity, it'd be better for sets to fit into 32 bits, I believe. But if they don't, then... set SChars { a = 'a', b, c , ... }

Feb 20 2002
parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:a4vok0$n4e$1 digitaldaemon.com...
 Some architectures out there have 128 bit registers... wouldn't want them

 feel overpowered would we?  ;)  Besides, you can just continue chaining
 together registers until you have enough bits... they are flags after all,
 there's no carry to worry about;  It's not nearly as complicated as, say,
 long division.  So I wouldn't advise imposing an absolute limit.  Pascal
 sets had a limit of 256 bits and that wasn't enough from what I remember
 trying to use it for sometimes.

There are only 3 numbers in computers: 0, 1, and any number. Any oddball limits, like 256 bits, 6 windows, 80 character command lines, etc., is a bug <g>. Take quicken's checkbook program, for example. It is so enormous it fills a CD. But I can only type in 10 characters or so into the [memo] field. Go figure.
Feb 20 2002