Topic: Proposal: enum flag extension
Author: 520001085531-0001@t-online.de ("Uenal Mutlu")
Date: Thu, 12 May 2005 06:44:36 GMT Raw View
And me wonders why the following is still not possible in C++:
enum TEA
{
E1, E2, E3
};
enum TEB : TEA
{
E4, E5
};
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 May 2005 05:04:38 GMT Raw View
Uenal Mutlu wrote:
> And me wonders why the following is still not possible in C++:
> enum TEA { E1, E2, E3 };
> enum TEB : TEA { E4, E5 };
Because this "derivation" is exactly the opposite of class derivation.
Every TEA is also a TEB, but every TEB is not a TEA.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: 520001085531-0001@t-online.de ("Uenal Mutlu")
Date: Fri, 13 May 2005 15:57:18 GMT Raw View
"Hyman Rosen"
> Uenal Mutlu wrote:
> > And me wonders why the following is still not possible in C++:
> > enum TEA { E1, E2, E3 };
> > enum TEB : TEA { E4, E5 };
>
> Because this "derivation" is exactly the opposite of class derivation.
> Every TEA is also a TEB, but every TEB is not a TEA.
No. Why should it?
IMO every TEB is also a TEA, but every TEA is not a TEB, and
this is the expected behavior, and it's exactly the same like when using classes.
So there is IMO no reason (ie. any problem) for not adding this to the language.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hyrosen@mail.com (Hyman Rosen)
Date: Sat, 14 May 2005 02:44:39 GMT Raw View
Uenal Mutlu wrote:
> IMO every TEB is also a TEA, but every TEA is not a TEB, and
> this is the expected behavior, and it's exactly the same like when using classes.
> So there is IMO no reason (ie. any problem) for not adding this to the language.
Excuse me? TEB contains extra enumerators beyond TEA. So if you allow
TEB teb = E5;
TEA tea = teb; // Now tea == E5 ??!!!
then tea now contains an illegal value.
With classes,
struct TEA { int x; };
struct TEB : TEA { int y; };
TEB teb; teb.x = 1; teb.y = 2;
TEA tea = teb; // Fine. tea.x == 1
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: 520001085531-0001@t-online.de ("Uenal Mutlu")
Date: Mon, 16 May 2005 16:22:43 GMT Raw View
Hyman Rosen wrote
> Uenal Mutlu wrote:
> > IMO every TEB is also a TEA, but every TEA is not a TEB, and
> > this is the expected behavior, and it's exactly the same like when using classes.
> > So there is IMO no reason (ie. any problem) for not adding this to the language.
>
> Excuse me? TEB contains extra enumerators beyond TEA. So if you allow
> TEB teb = E5;
> TEA tea = teb; // Now tea == E5 ??!!!
> then tea now contains an illegal value.
I see. But I have the feeling that inheritance should still be
made possible with enum-like values, either by extending the
existing enum concept (for example by using an implicitly added
method named isnull() or so), or introducing a completely new
way for this. I think the latter would be easier to implement.
If the value is invalid then it should return a userdefined null value.
Here's a possible concept:
xenum<-9> B { E1, E2, E3 }; // nullvalue is -9
xenum<-5> D1 : B { E4, E5 }; // nullvalue is -5
xenum<> D2 : D1 { E6, E7 }; // nullvalue is -1 (the default)
xenum D3 : D1, B { E7, E8 }; // nullvalue is -1 (the default)
D2 d2 = E6; // d2 has value of E3 (ie. 2)
D1 d1 = d2; // d1 will be the userdefined nullvalue (-5) for D1
B b = d1; // b is nullvalue (-9)
b = d2; // b is nullvalue (-9)
Multiple inheritance should be possible.
There are the following implicit methods of xenum:
T getnullvalue(); // returns the user defined null value (T is implicitly the type of the xenum)
bool isnull(); // returns whether the value is the nullvalue
User code can make use of these methods.
As an example: such a method would allow extending a 3rd party
class/library without the need for modifying the 3rd party code.
Currently this (enum extension) is not possible without modifying
the original enum declaration.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: SeeWebsiteForEmail@moderncppdesign.com ("Andrei Alexandrescu (See Website For Email)")
Date: Mon, 16 May 2005 16:21:27 GMT Raw View
Uenal Mutlu wrote:
> "Hyman Rosen"
>
>>Uenal Mutlu wrote:
>>
>>>And me wonders why the following is still not possible in C++:
>>>enum TEA { E1, E2, E3 };
>>>enum TEB : TEA { E4, E5 };
>>
>>Because this "derivation" is exactly the opposite of class derivation.
>>Every TEA is also a TEB, but every TEB is not a TEA.
>
>
> No. Why should it?
> IMO every TEB is also a TEA, but every TEA is not a TEB, and
> this is the expected behavior, and it's exactly the same like when using classes.
> So there is IMO no reason (ie. any problem) for not adding this to the language.
That's backwards. Inheritance would mean that a function getting a TEA
should be prepared for any value (because now TEA would be any
enumeration that includes E1=0, E2=1, and E3=2), which is contrary to
the currently accepted view on enumerated values (which is, you look at
the definition and get an idea about all of its possible values).
Andrei
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: christoph.seifert@gmx.net (Christoph Seifert)
Date: Sun, 8 May 2005 17:15:22 GMT Raw View
Hello!
I am sorry, if I might pick up some old idea. I am missing
some extension of the enum keyword though.
The Problem:
===========
I am using enums for a type-safe interface for some
functions e.g. enum types { bla, blub, ... };
using it in say
do_something(const string& text, types type);
If I am using flags though like in
fl.open(ios::out | ios::append), I have to define the
parameter of open as being an integer i.e. open(int);,
which removes the type-safety of the function
parameter. This is due to the |, & etc. operators returning
an integer.
Checking the standard library, I see, that there is
already a type-safe interface implemented.
This solution though is at the cost of many lines of
rather akward if tricky code, which includes
defining bitwise operators for openmode types like ios::append.
Suggestion No. 1:
================
extend the enum keyword (or introducing some new keyword)
e.g. enum_flags ios_flags { out, append, ... };
the value of out is automatically (1<<0) = 1,
the value of append is (1 << 1) = 2 etc.
Any combination of existing flags e.g. ios::append | ios::out
would be a valid ios_flags number as well by default.
Advantage:
I would achieve the same type-safety as with the
openmode example of the ios_base class - with
a lot of lines less in the source code, lettting
it shrink to a mere line of declaration.
Looking forward for comments!
Sincerly,
Christoph Seifert
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: max.teneyck.woodbury@verizon.net ("Max T. Woodbury")
Date: Sun, 8 May 2005 23:52:16 GMT Raw View
Christoph Seifert wrote:
> extend the enum keyword (or introducing some new keyword)
>
> e.g. enum_flags ios_flags { out, append, ... };
This is quite an old problem and has traditionally been solved
with enum and macros. My personal opinion is that a different
approach is needed largely because the problem lies elsewhere in
the language -- namely with bit-fields.
I know of two major uses for bit-fields:
- Packing restricted range values into a compact space.
- Interface with external equipment.
The two uses have different requirements with the interface
application being the more restrictive. As the language is
currently defined, it is very difficult (but not impossible)
to use bit-fields to specify a hardware interface. As a result
bit-wise operators with enum values are used usually used to
implement this kind of application.
The first and most significant problem with using bit-fields
for interfaces is the fact that the order of allocation of
bit-fields is implementation defined and thus NOT portable.
There is also a problem with specifying the size of the
object being transferred through the interface.
A good solution would also allow BOTH bit-field and bit-wise
operations to be used on an interface.
I think it might be possible to restructure the language to
do this better. The following is a rough draft for a proposal
that might be usable:
1) The data type of a bit field specifies the access width.
Traditionally, 'char' is the narrowest accessible type,
'short' the next less narrow with 'int', 'long' and 'long
long' being wider and wider types. (This is a non-decreasing
sequence, but not necessarily an increasing sequence.)
2) The address of the store containing the bit-field changes
when:
a) the data type of the fields changes,
b) there is no room int the store for the specified number
of bits, or
c) a zero width bit field is specified. (See item 6 below for
more details.)
For this purpose the 'signedness' of the data type is
ignored.
3) The sign of the width determines which end of the store the
field is allocated from:
:+n) allocates bits from the least significant end of the
unassigned bits in the store, and
:-n) allocates bits from the most significant end of the
unassigned bits in the store.
Note that 'n' can be a compile time constant expression and
need not start with a literal '-' character.
4) The width of a bit-field may be specified indirectly by
(ab)using the enum keyword. The width of the field will
be the number of bits needed to hold the largest enumerated
value. A ': signed enum' is is allocated from the most
significant end of the unassigned bits in the store while an
': unsigned enum' is allocated from the least significant end
of the unassigned bits in the store.
Note: The absence of either 'signed' or 'unsigned' in this
context is ambiguous and warrants a diagnostic. Also, all
enumerated values shall not be negative.
5) A bit-field does NOT require a name, however without a
name, it will not be possible to access the specified set
of bits as a bit-field.
6) The name of the zero width bit field provides access to
the entire store so that bit-wise and integer arithmetic
operations can be performed on the store. If the zero width
bit field for a store is not named or is not present, no
bit-wise or integer arithmetic operations can be applied to
the store as a whole. For the sake of the following
discussion, the object designated as having zero width is
not technically a bit-field and do not have any of the
special members described in the next item (7).
7) Bit-fields have three special members:
.mask is a compile time constant that can be used with
bit-wise operators to isolate the bit-field in the
store. (See item 6 for the way to designate access
to the store as a whole.)
[If absolutely required, this value could be
constructed from the .bit and .width members
described below.]
.bit is a compile time constant that designates the low
order bit of the field within the store. (See item 6
for the way to designate access to the store as a
whole.)
[It is tempting, but not absolutely necessary, to
specify a member with the value '1 << field.bit'.]
.width is a compile time constant that designates the
width of the bit-field in bits.
Note that these are NOT keywords in the usual sense.
8) The address of a bit-field is that address of the whole
store containing the bit-field. (On a machine with 8
bit characters and 32 bit long integers, the address of
a 'long' bit-field at bit offset 8 would be the address
of the long as a whole, not the address of the character
within the long containing that bit.)
An example might be useful: It should be possible to access
the various fields in a typical 'float' with the following
type:
struct float_fields { // 32 bits total..
signed long sign : -1; // The sign bit
unsigned long expo : -8; // 8 bits of biased exponent
unsigned long frac : -23; }; // 23 bits of varying fraction bits
or
struct float_fields { // 32 bits total..
unsigned long frac : 23; // 23 bits of varying fraction bits
unsigned long expo : 8; // 8 bits of biased exponent
signed long sign : 1; }; // The sign bit
max@mtew.isa-geek.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: christoph.seifert@gmx.net (Christoph Seifert)
Date: Tue, 10 May 2005 01:32:09 GMT Raw View
Hello,
thank you very much for your comment!
I think my statement might have been a bit
confusing.
I still think, that an implementation
as in the standard library with enum,
declarations of variables and declaration
of bitwise operators is akward at best
and lengthy at the very least.
That's why I was suggesting some nice shortcut
for implementing a type-safe interface with
flags like ios::app, which handles bitwise
operators like | e.g. ios::out | ios::append
as well.
Your proposal aims at the portability
of bitfields for use with hardware interfaces.
This I think is a different, though
very important field.
Sincerely,
Christoph Seifert
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]