Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Pascal-like set class

Reply
Thread Tools

Pascal-like set class

 
 
Rich Herrick
Guest
Posts: n/a
 
      09-04-2004
The latest version of my "Pascal-like" set class is available here:

http://www.richherrick.com/software/herrick-1.0.zip

Those from the old YAHOO BOOST forum might remember it from several months
back. I have enhanced the code, and "deboostifized" it.

For those unfamiliar with it, it is a template class that implements set
classes that are similar to the set type in the Pascal language. Like
Pascal, any integer (ordinal) type may be used with the set, but I mainly
wrote it for use with enumerations. Set elements are stored at the bit
level, so it is every compact. There is even a member template for defining
set objects as compile-time constants. I wrote it because none of the C++
containers (i.e., set and bitset) suited my needs.

A big change from older versions is the addition of a traits template
parameter for use gaining finer control over the class' behavior for such
things as bit ordering and element range (which defaults to [0,
number-of-elements - 1]).

Examples from documentation:

declaration:
enum color_type
{NON_COLOR = -1, RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET,
NUM_COLORS};

typedef herrick:ascal_set<color_type, NUM_COLORS> color_set;

compile-time constants:
const color_set additive_primaries =
color_set::setof<RED, GREEN, BLUE>::value;

const color_set subtractive_primaries =
color_set::setof<RED, YELLOW, BLUE>::value;

I'd be very interested in comments about the code, the interface (I may have
went overboard on operators!), or my use of templates (I still get hazy on
when to use "typename" and "template").

My goal is to have the interface as much as like the Pascal set type as
feasible, while having the code conform to the lated standard (regardless
particular compiler conformity).

The code currenty compilers with:
GCC 3.4.0 (MinGW)
Visual C++ Toolkit 2003


Rich Herrick





 
Reply With Quote
 
 
 
 
David Hilsee
Guest
Posts: n/a
 
      09-05-2004
"Rich Herrick" <> wrote in
message news:hXq_c.59663$...
<snip>
> I'd be very interested in comments about the code, the interface (I may

have
> went overboard on operators!), or my use of templates (I still get hazy on
> when to use "typename" and "template").

<snip>

I think you did go overboard on the operators. Most of the operators for
that class do not stick to their traditional meaning. Some are close calls,
but the definitions of operator bool, !, <, <=, >, >=, <<, >>, /, and * look
odd to me.

--
David Hilsee


 
Reply With Quote
 
 
 
 
Rich Herrick
Guest
Posts: n/a
 
      09-05-2004

"David Hilsee" <> wrote in message
news:8-KdnQTFFvNYFabcRVn-...
> "Rich Herrick" <> wrote in
> message news:hXq_c.59663$...
> <snip>
> > I'd be very interested in comments about the code, the interface (I may

> have
> > went overboard on operators!), or my use of templates (I still get hazy

on
> > when to use "typename" and "template").

> <snip>
>
> I think you did go overboard on the operators. Most of the operators for
> that class do not stick to their traditional meaning. Some are close

calls,
> but the definitions of operator bool, !, <, <=, >, >=, <<, >>, /, and *

look
> odd to me.
>
> --
> David Hilsee
>
>


Thanks for replying. All the relational ones match how Pascal defines them,
and are needed to do subset/superset comparisions. The / and * operators
are also how Pascal defines them for doing symmetric difference and
intersection, respectively. There really isn't an operator bool, its really
operator void*, which will allow testing for a non-empty set in an if
statement without the nasty side-effects you will get with operator bool.
Though I will admit that operator void* and operator ! aren't really needed,
as there is a member that will test for an empty set (and you could also
test for equals to NULL_SET). The ones I knew someone would question are >>
and <<, as I almost took them out several times. But I just like the way
they "look" for adding elements to a set. There is a + operator that does
the same thing, but I think "S + e1 + e2" looks confusing, especially if e1
and e2 are integers: S + 1 + 2. I think S << 1 << 2 appears more readable
in code. Besides, the former creates a new set and the later does not, and
S += 1 + 2 will, of course, not work. Though again there are many other
ways to add elements to the set such as: S *= set_type(e1, e2), which will
union S with the new set, the result of which is in S.

Thanks,

Rich Herrick


 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      09-06-2004
"Rich Herrick" <> wrote in
message news:zBM_c.60065$...
<snip>
> Thanks for replying. All the relational ones match how Pascal defines

them,
> and are needed to do subset/superset comparisions. The / and * operators
> are also how Pascal defines them for doing symmetric difference and
> intersection, respectively. There really isn't an operator bool, its

really
> operator void*, which will allow testing for a non-empty set in an if
> statement without the nasty side-effects you will get with operator bool.
> Though I will admit that operator void* and operator ! aren't really

needed,
> as there is a member that will test for an empty set (and you could also
> test for equals to NULL_SET). The ones I knew someone would question are
>>

> and <<, as I almost took them out several times. But I just like the way
> they "look" for adding elements to a set. There is a + operator that does
> the same thing, but I think "S + e1 + e2" looks confusing, especially if

e1
> and e2 are integers: S + 1 + 2. I think S << 1 << 2 appears more readable
> in code. Besides, the former creates a new set and the later does not,

and
> S += 1 + 2 will, of course, not work. Though again there are many other
> ways to add elements to the set such as: S *= set_type(e1, e2), which will
> union S with the new set, the result of which is in S.


I'll buy the other operators, but I think that <<, >>, !, nad operator void*
are, at the very least, questionable. Also, the == and != for set
membership seem odd, because I pronounce the code "If element e is equal to
set s" when it really means "if set s contains element e".

A few more questions:

Why does the traits class provide the array element type? Why would anyone
want to customize the element?

Why even bother with an array? Why does std::bitset not provide what you
need? It took me a few minutes to wrap my head around the "traits" code,
and then I realized that it was basically implementing std::bitset. I think
that's what it's doing, anyway.

--
David Hilsee


 
Reply With Quote
 
Rich Herrick
Guest
Posts: n/a
 
      09-06-2004

"David Hilsee" <> wrote in message
news:2OSdnYhAfKCBRqbcRVn-...
> "Rich Herrick" <> wrote in
> message news:zBM_c.60065$...
> <snip>
> I'll buy the other operators, but I think that <<, >>, !, nad operator

void*
> are, at the very least, questionable. Also, the == and != for set
> membership seem odd, because I pronounce the code "If element e is equal

to
> set s" when it really means "if set s contains element e".

I agree. To be honest, I had forget about the == and != operators, and in
my code I use the contains() member. I think I will remove them on future
releases. But I still waffle back and forth on << and >>. I can see where
they are extraneous, but I tend to like and use them a lot. The ! and void*
operator I will probably remove also.

>
> A few more questions:
>
> Why does the traits class provide the array element type? Why would

anyone
> want to customize the element?

Because, the reason I wrote it was because I wanted low-level control of the
layout and the size. If I have a set with n items and n <= CHAR_BIT, I may
want to fit them all into am unsigned char instead of an unsigned int. I do
a lot of embedded software, dealing with drivers and memory-mapped registers
and such. I'm use to have that kind of control, and tend to write
interfaces with that in mind. I also deal with resources that are more
constrained than an app. writer on a PC might. So, I guess the simple
answer to your question is they wouldn't, except when the array is only one
element in size, then I may want to use the smallest int type I can.


>
> Why even bother with an array? Why does std::bitset not provide what you
> need? It took me a few minutes to wrap my head around the "traits" code,
> and then I realized that it was basically implementing std::bitset. I

think
> that's what it's doing, anyway.

Depends on what you are asking. If you are asking why pascal_set instead of
bitset, then the answer is pascal_set is more typesafe then bitset and I
want to mimic the Pascal set type as closely as I could, although I suppose
I could have just wrapped bitset inside pascal_set. If you are asking why I
didn't just wrap bitset inside my class instead of using an array, it comes
down to control. I wanted control of the size and control of the bit-order.
A lot of what I do interfaces with other languages (I write a lot of C, C++
and Ada--both '83 and '95), and memory-mapped registers. I have to know the
layout. pascal_set makes it nice when dealing with set of bit flags in a
memory-mapped register or an Ada bit array. Though its implementation
specific, Ada compilers tend to use the MSB as bit 0 on a big-endian machine
and the LSB as bit 0 on a little-endian machine. I wanted to be able to set
my bit order to match. Plus, I want to see if I could use templates to
create compile-set constant sets, which I may not be able to do with bitset.
This is how the setof template evolved.

My reasons probably aren't good enough for someone looking for a set class
to choose mine over bitset or even set. But that's OK, I wrote it for me,
and found it useful and a joy to use and thought to share it with anyone you
may be interested. I am currently using it recreationally in writing some
Interactive Fiction.

And while writing this, I just thought of a big bug in the whole "traits"
thing I must now fix....

Regards.

--
Rich Herrick


 
Reply With Quote
 
Rich Herrick
Guest
Posts: n/a
 
      09-06-2004
By the way David, what is your opinion of the constructors provided? Too
much?

Thanks

--
Rich Herrick


 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      09-06-2004
"Rich Herrick" <> wrote in
message news:WpS_c.9672$...
<snip>
> Because, the reason I wrote it was because I wanted low-level control of

the
> layout and the size. If I have a set with n items and n <= CHAR_BIT, I

may
> want to fit them all into am unsigned char instead of an unsigned int. I

do
> a lot of embedded software, dealing with drivers and memory-mapped

registers
> and such. I'm use to have that kind of control, and tend to write
> interfaces with that in mind. I also deal with resources that are more
> constrained than an app. writer on a PC might. So, I guess the simple
> answer to your question is they wouldn't, except when the array is only

one
> element in size, then I may want to use the smallest int type I can.


I understand that, but I'm surprised that there would be cases where you
would want to use an unsigned char, and other cases where you would want to
use an unsigned int. In the latter case, wouldn't you just use multiple
unsigned chars? I've never done embedded programming, so I might be
overlooking something. Is there an alignment issue?

--
David Hilsee


 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      09-06-2004
"Rich Herrick" <> wrote in
message newsNS_c.9673$...
> By the way David, what is your opinion of the constructors provided? Too
> much?

<snip>

I don't see any problem with them. Many might be unnecessary, though,
thanks to the ones that take arrays. I can see how they look a tad nicer
than the equivalent code that uses arrays, though.

--
David Hilsee


 
Reply With Quote
 
Rich Herrick
Guest
Posts: n/a
 
      09-06-2004

"David Hilsee" <> wrote in message
news:EqidnZoW9IOX46HcRVn-...

> I understand that, but I'm surprised that there would be cases where you
> would want to use an unsigned char, and other cases where you would want

to
> use an unsigned int. In the latter case, wouldn't you just use multiple
> unsigned chars? I've never done embedded programming, so I might be
> overlooking something. Is there an alignment issue?
>
> --
> David Hilsee
>

Well, one reason would be a memory-mapped register accessed across a VME
bus. If a 16-bit register that is mapped as a D16 access, but you attempt
to access it as a D32 or 2 D8, you will get a data access exception. Same
with an 8-bit register. So, if I make the underlining type match (which
again is implementation specific), I can access it with my class.

If I had a large set, then sure, I would use int, because the set operations
are done on a whole int at a time, not bit. So, on a platform where int is
32 bits, and I had a set with 64 elements, it would do a union in two
operations, not 64. But, on the other hand, if I may be more concerned with
size. If, assuming char is 8 bits, and I need my set to fit into 24 bits
(maybe its in a struct talking to an Ada record, and Ada had a
representation specification that maps it into 24 bits), I can achieve this
by setting the unit type to unsigned char. I would be trading efficiency to
make it fit, but that would probably not be an issue.

--
Rich Herrick


 
Reply With Quote
 
Rich Herrick
Guest
Posts: n/a
 
      09-06-2004

"David Hilsee" <> wrote in message
news:bOGdnZJug8GHHaHcRVn-...
> "Rich Herrick" <> wrote in
> message newsNS_c.9673$...
> > By the way David, what is your opinion of the constructors provided?

Too
> > much?

> <snip>
>
> I don't see any problem with them. Many might be unnecessary, though,
> thanks to the ones that take arrays. I can see how they look a tad nicer
> than the equivalent code that uses arrays, though.
>
> --
> David Hilsee
>
>

I wrote the multitude of constructors that take different numbers of
elements for type-safety (over var. length args.) and efficiently. I was
wondering if maybe the array ones were too much (especially since there is
two of them).

Thanks for your insights.

--
Rich Herrick


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Class A contains class B, class B points to class A Joseph Turian C++ 5 12-30-2005 03:24 PM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
Creating inherited class with set base class Josh Mcfarlane C++ 2 08-18-2005 05:31 PM
A parameterized class (i.e. template class / class template) is not a class? christopher diggins C++ 16 05-04-2005 12:26 AM
How do you set the class path for groups of class files in nested directories? keith edward Java 1 04-07-2004 11:09 PM



Advertisments