By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,727 Members | 1,151 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,727 IT Pros & Developers. It's quick & easy.

A simple validity check. But need your kind help!

P: n/a
Dear All,

Assume I have a class for a cuboid domain. The domain is defined by
the cuboid's lower corner, such as (0, 0, 0), and upper corner, such
as (1, 1, 1). The upper corner should be always higher than the lower
corner. I write a code as below

class Domain
{
private:
double mLowerCorner[3];
double mUpperCorner[3];

public:
double* GetLowerCorner() {return mLowerCorner;}
double* GetUpperCorner() {return mUpperCorner;}

void SetLowerCorner(double lowerCorner[3])
{
if (mUpperCorner[0] < lowerCorner[0] || // Validity check
mUpperCorner[1] < lowerCorner[1] ||
mUpperCorner[2] < lowerCorner[2] )
{
throw out_of_range("Error");
}
mLowerCorner[0] = lowerCorner[0];
mLowerCorner[1] = lowerCorner[1];
mLowerCorner[2] = lowerCorner[2];
}

// My question is here: I need similar functions
// void SetUpperCorner(double upperCorner[3]),
// void SetDomain(double lowerCorner[3], double upperCorner[3]),
// and constructors.
// and so on. The check make me very uncomfortable.
};

Anyone can give me a good suggestion to solve the problem?

Thanks a lot!

Shuisheng

Feb 16 '07 #1
Share this Question
Share on Google+
2 Replies


P: n/a
shuisheng wrote:
Dear All,

Assume I have a class for a cuboid domain. The domain is defined by
the cuboid's lower corner, such as (0, 0, 0), and upper corner, such
as (1, 1, 1). The upper corner should be always higher than the lower
corner. I write a code as below

class Domain
{
private:
double mLowerCorner[3];
double mUpperCorner[3];

public:
double* GetLowerCorner() {return mLowerCorner;}
double* GetUpperCorner() {return mUpperCorner;}
These methods expose the arrays. Client code could say:

(GetLowerCorner())[1] = 2.0;

and change the entries. In that case, the client will bypass all validity
checks whatsoever. At least, you need:

double const * GetLowerCorner() const {return mLowerCorner;}
double const * GetUpperCorner() const {return mUpperCorner;}
void SetLowerCorner(double lowerCorner[3])
{
if (mUpperCorner[0] < lowerCorner[0] || // Validity check
mUpperCorner[1] < lowerCorner[1] ||
mUpperCorner[2] < lowerCorner[2] )
{
throw out_of_range("Error");
}
mLowerCorner[0] = lowerCorner[0];
mLowerCorner[1] = lowerCorner[1];
mLowerCorner[2] = lowerCorner[2];
}

// My question is here: I need similar functions
// void SetUpperCorner(double upperCorner[3]),
// void SetDomain(double lowerCorner[3], double upperCorner[3]),
// and constructors.
// and so on. The check make me very uncomfortable.
};
What should make you uncomfortable is not the checks but the sheer
complexity you are inviting just to deal with two points in space.

What about making domains immutable and putting a little more intelligence
into the points:

#include <tr1/array>
#include <stdexcept>

// warning: [bad hack, there is no guarantee that we can derive from array]
/*
(a) We use derivation rather than a typedef so that operator- only applies
to this type.
(b) Some people will prefer to derive privately and import all methods via
using directives.
*/
struct vector3d : public std::tr1::array<double,3{

vector3d ( double x = 0.0,
double y = 0.0,
double z = 0.0 )
{
(*this)[0] = x;
(*this)[1] = y;
(*this)[2] = z;
}

};

vector3d operator- ( vector3d const & lhs, vector3d const & rhs ) {
vector3d result;
for ( unsigned i = 0; i < 3; ++i ) {
result[i] = lhs[i] - rhs[i];
}
return ( result );
}
bool is_strictly_positive ( vector3d const & v ) {
for ( unsigned i = 0; i < 3; ++i ) {
if ( v[i] <= 0 ) {
return ( false );
}
}
return ( true );
}

bool does_define_box ( vector3d const & bot,
vector3d const & top ) {
return ( is_strictly_positive( top - bot ) );
}

class immutableDomain {

vector3d bot;
vector3d top;

public:

immutableDomain ( vector3d const & b, vector3d t )
: bot(b)
, top(t)
{
if ( ! does_define_box( bot, top ) ) {
throw std::out_of_range( "Error" );
}
}

vector3d const & lowerCorner ( void ) const {
return ( bot );
}

vector3d const & upperCorner ( void ) const {
return ( top );
}

};

If you want to, you can define a mutable Domain class wrapping around the
immutable one:

class Domain {

immutableDomain the_data;

public:

Domain ( vector3d const & b, vector3d const & t )
: the_data( b, t )
{}

vector3d const & getLowerCorner ( void ) const {
return ( the_data.lowerCorner() );
}

vector3d const & getUpperCorner ( void ) const {
return ( the_data.upperCorner() );
}

void setLowerCorner ( vector3d const & bot ) {
the_data = immutableDomain( bot, the_data.upperCorner() );
}

void setUpperCorner ( vector3d const & top ) {
the_data = immutableDomain( the_data.lowerCorner(), top );
}

};

The constructor of immutableDomain will be the only place where the
invariant is checked.
Best

Kai-Uwe Bux
Feb 16 '07 #2

P: n/a
In article <11**********************@v45g2000cwv.googlegroups .com>,
sh*********@yahoo.com says...
Dear All,

Assume I have a class for a cuboid domain. The domain is defined by
the cuboid's lower corner, such as (0, 0, 0), and upper corner, such
as (1, 1, 1). The upper corner should be always higher than the lower
corner. I write a code as below
I'd add private functions to check the condition, and do the assignment.
Using this, the rest become pretty trivial:

class Domain {
double mLowerCorner[3];
double mUpperCorner[3];

bool check(double *lower, double *upper) {
if (upper[0] < lower[0] ||
upper[1] < lower[1] ||
upper[2] < lower[2])
throw out_of_range("Error");
}

void assign(double &a, double const &b) {
a[0] = b[0];
a[1] = b[1];
a[2] = b[2];
}

public:
void SetLowerCorner(double lower[3]) {
check(lower, mUpperCorner);
assign(mLowerCorner, lower);
}

void SetUpperCorner(double upper[3]) {
check(mLowerCorner, upper);
assign(mUpperCorner, upper);
}

void SetDomain(double *lower, double *upper) {
check(lower, upper);
assign(mLowerCorner, lower);
assign(mUpperCorner, upper);
}

Domain(double *lower, double *upper) {
SetDomain(lower, upper);
}
// ...
};

--
Later,
Jerry.

The universe is a figment of its own imagination.
Feb 16 '07 #3

This discussion thread is closed

Replies have been disabled for this discussion.