A simple validity check. But need your kind help!

Discussion in 'C++' started by shuisheng, Feb 16, 2007.

  1. shuisheng

    shuisheng Guest

    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
     
    shuisheng, Feb 16, 2007
    #1
    1. Advertising

  2. shuisheng

    Kai-Uwe Bux Guest

    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 = 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
     
    Kai-Uwe Bux, Feb 16, 2007
    #2
    1. Advertising

  3. shuisheng

    Jerry Coffin Guest

    In article <>,
    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.
     
    Jerry Coffin, Feb 16, 2007
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Martin Burger
    Replies:
    3
    Views:
    571
    Roland
    Jun 30, 2005
  2. Rex_chaos
    Replies:
    3
    Views:
    332
    tom_usenet
    Oct 28, 2003
  3. Replies:
    0
    Views:
    378
  4. Merrycoder

    check validity of a controls property at compile time

    Merrycoder, Apr 17, 2008, in forum: ASP .Net Building Controls
    Replies:
    1
    Views:
    749
    Peter Bucher [MVP]
    May 1, 2008
  5. Marc Pichouron

    Search a keyword but but only on one kind of tag

    Marc Pichouron, Jan 8, 2004, in forum: Javascript
    Replies:
    0
    Views:
    109
    Marc Pichouron
    Jan 8, 2004
Loading...

Share This Page