A simple validity check. But need your kind help!

S

shuisheng

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
 
K

Kai-Uwe Bux

shuisheng said:
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 = lhs - rhs;
}
return ( result );
}


bool is_strictly_positive ( vector3d const & v ) {
for ( unsigned i = 0; i < 3; ++i ) {
if ( v <= 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::eek:ut_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
 
J

Jerry Coffin

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);
}
// ...
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top