473,385 Members | 1,919 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Objects with value semantics - enums vs classes

The problem comes up in all sorts of contexts. But here is an example:

We want to model the basics of chess, maybe for making a chess program,
or maybe just to make an interactive board or ...

We have to have the notions of colors, squares and pieces represented.
Ideally, we want to be able to do things like initializing the board:

void initial()
{
const Piece backLine[] =
{rook,knight,bishop,queen,king,bishop,knight,rook} ;

toMove = white;
int i = 0;
for (square s = a1; s <= h1; ++s)
{
board[s].piece = backLine[i++];
board[s].color = white;
}
for (square s = a2; s <= h2; ++s)
{
board[s].piece = pawn;
board[s].color = white;
}
for (square s = a3; s <= h6; ++s)
board[s].piece = none;
for (square s = a7; s <= h7; ++s)
{
board[s].piece = pawn;
board[s].color = black;
}
i = 0;
for (Square s = a8; s <= h8; ++s)
{
board[s].piece = backLine[i++];
board[s].color = black;
}
}

This is a simple function that has to be present in a program involving
chess, and it shows a little bit about what is needed.

The simplest way to do this, is by making enums for piece, color, and
square, like:

enum Color {white,black};
enum Piece {none,pawn,knight,bishop,queen,king}
enum Square {a1,a2,...,h8};

But already here, we are having trouble. We have to define several
functions to get Square to work as indicated above.

We could do it even simpler and less typesafe by just using ints. Then
we would have our value semantics; assignment, comparison,
incrementation etc.

And we could make everything a class. But how?
Then one would have to go through the tedious process of defining all
the operators necesary for value semantics.

In SML, one would just do

datatype Piece = none | pawn | ... | king;

(or something like that... My SML is rusty).

In Ada, one can do something similarly.

This sort of thing, defining a collection of values of the same kind,
being able to assign them, and iterate through them etc., but as typed
_values_, not as ints, is pretty essential as I see it.

I don't really know what my question is :)
Maybe this:

What is the _intended_ C++ way of solving this _kind_ or _class_ or
_type_ of problem?
What is the kosher OOP way to do it?

I know that one can make a hierachy like

class Color
{};

class White : public Color
{}

class Black : public Color
{}

or whatever...

But then, how will the above function look? I can't do

toMove = white;

then.

In short:

What would be a nice flexible and (type)safe design of such things?
Please give an example of how to define Color, Piece and Square, and an
outline of what the initial() function will look like.

I think this kind of problem occurs all the time.

/David

Jul 22 '05 #1
4 2251
"David Rasmussen" <da*************@gmx.net> wrote:
This sort of thing, defining a collection of values of the same kind,
being able to assign them, and iterate through them etc., but as typed
_values_, not as ints, is pretty essential as I see it.

What is the _intended_ C++ way of solving this _kind_ or _class_ or
_type_ of problem?
What is the kosher OOP way to do it?


There is an article on various things you can do with enums called "Stupid
Enumeration Tricks" (don't be put off by the title) in:

http://www.edm2.com/0405/enumeration.html

Hope this is helpful,

David F
Jul 22 '05 #2
David Rasmussen wrote:
The problem comes up in all sorts of contexts. But here is an example:

We want to model the basics of chess, maybe for making a chess program,
or maybe just to make an interactive board or ...

We have to have the notions of colors, squares and pieces represented.
Ideally, we want to be able to do things like initializing the board:

void initial()
{
const Piece backLine[] =
{rook,knight,bishop,queen,king,bishop,knight,rook} ;

toMove = white;
int i = 0;
for (square s = a1; s <= h1; ++s)
{
board[s].piece = backLine[i++];
board[s].color = white;
}
for (square s = a2; s <= h2; ++s)
{
board[s].piece = pawn;
board[s].color = white;
}
for (square s = a3; s <= h6; ++s)
board[s].piece = none;
for (square s = a7; s <= h7; ++s)
{
board[s].piece = pawn;
board[s].color = black;
}
i = 0;
for (Square s = a8; s <= h8; ++s)
{
board[s].piece = backLine[i++];
board[s].color = black;
}
}

This is a simple function that has to be present in a program involving
chess, and it shows a little bit about what is needed.

The simplest way to do this, is by making enums for piece, color, and
square, like:

enum Color {white,black};
enum Piece {none,pawn,knight,bishop,queen,king}
enum Square {a1,a2,...,h8};

#include <string>

class Color;
extern Color white;
extern Color black;

class Piece;
extern Piece pawn,knight,bishop,queen,king,rook;

class Square;
// I have no idea why you would want to enumerate these.

std::string Name( const Color & );
std::string Name( const Piece & );

inline bool operator==( const Color & b, const Color & a )
{
return &b == &a;
}

inline bool operator==( const Piece & b, const Piece & a )
{
return &b == &a;
}

inline bool operator<( const Color & b, const Color & a )
{
return &b < &a;
}

inline bool operator<( const Piece & b, const Piece & a )
{
return &b < &a;
}
In short:

What would be a nice flexible and (type)safe design of such things?
Please give an example of how to define Color, Piece and Square, and an
outline of what the initial() function will look like.
I would probably design it differently to what you have above.

I's add

class PlayingPiece;
extern PlayingPiece white_pawn;
extern PlayingPiece black_pawn;
extern PlayingPiece white_rook;
extern PlayingPiece black_rook;
.... etc

Then I would set up a static array:

struct BoardPositions
{
PlayingPiece * board_array[8][8];
};

BoardPositions initial_positions =
{
{
{ & black_rook, &black_knight, &black_bishop, ... etc
( & black_pawn, & black_pawn, & black_pawn, & black_pawn, ...
{ },
{ },
{ },
{ },
{ & white_pawn, & white_pawn, & white_pawn, & white_pawn, ...
{ & white_rook, & white_night, .... etc
}
};

struct Board
{
BoardPositions m_board_positions

Board()
m_board_positions( initial_positions )
{
}
}


I think this kind of problem occurs all the time.


I'd almost never use enums. Usually you're better off statically
creating an object that represents the concept.

.... I hope this helps.

Jul 22 '05 #3
David Fisher wrote:

There is an article on various things you can do with enums called "Stupid
Enumeration Tricks" (don't be put off by the title) in:

http://www.edm2.com/0405/enumeration.html

Hope this is helpful,


Thanks, it is!

And it also highlights some very basic problems that C++ has.

Let's take the simple example mentioned on that page: the days of the week.

Who would make a class for that, and make "monday", "tuesday" etc. be
instances of this class? Sometimes, you want to enumerate something, and
you know you'll never need to expand it or reuse it etc. In my opinion,
such "native" but smart enums, should be in the language for exactly the
same reason that ints and doubles should: they are very basic.
They should be typesafe (no implicit to-int conversion), have value
semantics, and they should support native iteration (for, while etc.) like:

for (weekday w = monday; w != sunday; ++w)
...;

Ada and a lot of other languages have this already. Bjarne Stroustrup's
view on this seems to be that we wouldn't like "too good" enums, because
then people would use them too much when an OOP approach would be better.

/David

Jul 22 '05 #4
David Rasmussen wrote:
David Fisher wrote:

There is an article on various things you can do with enums called
"Stupid
Enumeration Tricks" (don't be put off by the title) in:

http://www.edm2.com/0405/enumeration.html


The really funny thing is, that this article is 8 years old. And it
still touches upon some important core topics of C++.

/David

Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
by: Matteo Settenvini | last post by:
Ok, I'm quite a newbie, so this question may appear silly. I'm using g++ 3.3.x. I had been taught that an array isn't a lot different from a pointer (in fact you can use the pointer arithmetics to...
10
by: cody | last post by:
Why can't we use switches with singleton objects? I know that the compiler cannot optimize them like constant values but the same is true for strings and they are allowed in switches. The reason...
26
by: Brett | last post by:
I have created a structure with five fields. I then create an array of this type of structure and place the structure into an array element. Say index one. I want to assign a value to field3 of...
9
by: cody | last post by:
Why can't switch used for objects, at least for static readonly fields it wold be nice. The Jit could certainly optimize this case because the addresses of static readonly variables are known at...
0
by: NeoGeo | last post by:
Hi I'm using the PropertyGrid control, and implemented a popup menu to Reset properties, like the IDE The problem I have is that I'm unable to specify DefaultValues for enums and objects For...
3
by: The Petar | last post by:
I am really unhappy that C# accessors are not powerful enough to mimic as if you were accessing an class field. In particular, let S be: public struct S { public int v; public void change ()...
3
by: Ramon F Herrera | last post by:
Newbie alert: I come from C programming, so I still have that frame of mind, but I am trying to "Think in C++". In C this problem would be solved using unions. Hello: Please consider the...
41
by: process | last post by:
I have heard some criticism about Python, that it is not fully object- oriented. What is not an object in Python? Why isn't len implemented as a str.len and list.len method instead of a...
55
by: tonytech08 | last post by:
How valuable is it that class objects behave like built-in types? I appears that the whole "constructor doesn't return a value because they are called by the compiler" thing is to enable...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.