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

Rejecting negative number

P: n/a
Take a class like the following:

class Finger
{
public:

double length;
}
I'm writing reusable code and, being dictator, I dictate that "length"
cannot be negative. The following would be perfect:

unsigned double length;

But ofcourse doesn't compile.
So... I've come up with 3 potential solutions: A1 A2 B .
A) Create 2 separate member functions, GetLength and SetLength. SetLength
will reject negative numbers. When supplied with a negative number it will:
A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined behaviour if length is
set to a negative number.

Which would you suggest? Any other suggestions?
I myself am leaning toward B.
Thanks
-JKop

Jul 22 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a

"JKop" <NU**@NULL.NULL> wrote in message
news:_u***************@news.indigo.ie...
Take a class like the following:

class Finger
{
public:

double length;
}
I'm writing reusable code and, being dictator, I dictate that "length"
cannot be negative. The following would be perfect:

unsigned double length;

But ofcourse doesn't compile.
So... I've come up with 3 potential solutions: A1 A2 B .
A) Create 2 separate member functions, GetLength and SetLength. SetLength
will reject negative numbers. When supplied with a negative number it will: A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined behaviour if length is
set to a negative number.

Which would you suggest? Any other suggestions?
I myself am leaning toward B.


A1 without a doubt.

Also note that A1 is a subset of B, so you could document B but implement A1
if you really wanted to. When your users complain about the exception, you
just say 'I told you the behaviour was undefined'.

john
Jul 22 '05 #2

P: n/a
John Harrison posted:
A1 without a doubt.

Also note that A1 is a subset of B, so you could document B but
implement A1 if you really wanted to. When your users complain about
the exception, you just say 'I told you the behaviour was undefined'.

Thanks for the input.
I myself think that that would be too kind. "Undefined behaviour" means
exactly what it says on the tin. It's like saying to a child, "Yes, Go play
with the matches and the petrol - Just don't come running to _ME_ when
you've burned yourself". And ofcourse, any responsible parent would say,
"Don't play with the matches and the petrol!" and then actually physically
prevent the children from performing such actions.

But... we're all consenting adults here.
Although I still haven't made my decision yet.
All input appreciated.
Thanks
-JKop
Jul 22 '05 #3

P: n/a
JKop wrote:
Take a class like the following:

class Finger
{
public:

double length;
}
I'm writing reusable code and, being dictator, I dictate that "length"
cannot be negative. The following would be perfect:

unsigned double length;

But ofcourse doesn't compile.
So... I've come up with 3 potential solutions: A1 A2 B .
A) Create 2 separate member functions, GetLength and SetLength.
SetLength will reject negative numbers. When supplied with a negative
number it will: A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined behaviour if
length is set to a negative number.

Which would you suggest? Any other suggestions?
I myself am leaning toward B.
Thanks
-JKop


Make a small property template class that allows for range validation, like
this:

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

template <class T, class Modify>
class property
{
protected:
T var;
Modify mod;
public:
property<T, Modify>(const T& init, const Modify& m)
: mod(m), var(init)
{}

operator T()
{
return var;
}

property& operator =(const T& val)
{
if(!mod(val))
throw invalid_argument("bad property argument.");
var = val;
return *this;
}
};

template<class T>
struct RangeValidationPropModified
{
string msg;
T minval, maxval;
public:
RangeValidationPropModified<T>(string m, const T& minv, const T& maxv)
: msg(m),
minval(minv),
maxval(maxv)
{}

bool operator() (const T& val)
{
if(val >= minval && val <= maxval)
{
cout << msg;
return true;
}
else
return false;
}
};

int main(int argc, char* argv[])
{
property<int, RangeValidationPropModified<int> >
p(0, RangeValidationPropModified<int>("the property is being
modifed!\n", 0, 100));

cout << p << endl;
p = 5;
cout << p << endl;
p = 10;
cout << p << endl;
try
{
p = -1;
cout << p << endl;
p = 1000;
cout << p << endl;
}
catch(invalid_argument ex)
{
cout << ex.what() << endl;
}

system("pause");
return 0;
}

- Pete
Jul 22 '05 #4

P: n/a
Petec wrote:
JKop wrote: <snip>
operator T()
{
return var;
}
Should be:

operator T&()
{
return var;
}

To allow operators to be applied.

<snip>
Jul 22 '05 #5

P: n/a
*
?
"Petec" <x@x.x> wrote in message
news:CW****************@newsread2.news.pas.earthli nk.net...
Petec wrote:
JKop wrote:

<snip>

operator T()
{
return var;
}


Should be:

operator T&()
{
return var;
}

To allow operators to be applied.

<snip>

Jul 22 '05 #6

P: n/a
* wrote:
?
"Petec" <x@x.x> wrote in message
news:CW****************@newsread2.news.pas.earthli nk.net...
Petec wrote:
JKop wrote:

<snip>

operator T()
{
return var;
}


Should be:

operator T&()
{
return var;
}

To allow operators to be applied.

<snip>


??

Please don't top-post, BTW.

- Pete
Jul 22 '05 #7

P: n/a
"JKop" <NU**@NULL.NULL> wrote in message
news:_u***************@news.indigo.ie...
unsigned double length;

But ofcourse doesn't compile. A) Create 2 separate member functions, GetLength and SetLength. SetLength
will reject negative numbers. When supplied with a negative number it will: A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined behaviour if length is
set to a negative number.

Which would you suggest? Any other suggestions?


First choice = B for performance reasons, simplicity of code. The C++
standard does it all the time (ie. if iterator points to 2 plus end then
result is undefined, if std::sort compare function does not have strict weak
ordering then undefined behavior).

Second choice = A1. As a variation, only if NDEBUG is defined then do we
throw an exception.

Third choice = A2.
Jul 22 '05 #8

P: n/a
"Petec" <x@x.x> wrote in message news:<CW****************@newsread2.news.pas.earthl ink.net>...
Petec wrote:
JKop wrote:

<snip>

operator T()
{
return var;
}


Should be:

operator T&()
{
return var;
}

To allow operators to be applied.


No. If the restriction is that the value should be positive,
one cannot allow T::operator*=, someonce could pass -1. The same
applies for operator+=, opertaor/=, and (for positive arguments)
to operator-=.

The correct form is operator T() const;, as it won't modify var.

Regards,
Michiel Salters
Jul 22 '05 #9

P: n/a
Michiel Salters wrote:
"Petec" <x@x.x> wrote in message
news:<CW****************@newsread2.news.pas.earthl ink.net>...
Petec wrote:
JKop wrote: <snip>

operator T()
{
return var;
}


Should be:

operator T&()
{
return var;
}

To allow operators to be applied.


No. If the restriction is that the value should be positive,
one cannot allow T::operator*=, someonce could pass -1. The same
applies for operator+=, opertaor/=, and (for positive arguments)
to operator-=.

The correct form is operator T() const;, as it won't modify var.


Ahh, yes, I forgot about that. I'll implement the operators on it and post
back here...

- Pete

Regards,
Michiel Salters


Jul 22 '05 #10

P: n/a
> > A) Create 2 separate member functions, GetLength and
SetLength. SetLength will reject negative numbers. When
supplied with a negative number it

will:

A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined
behaviour if length is set to a negative number.

Which would you suggest? Any other suggestions?


First choice = B for performance reasons, simplicity of
code. The C++ standard does it all the time (ie. if
iterator points to 2 plus end then result is undefined,
if std::sort compare function does not have strict weak
ordering then undefined behavior).


I see your point, but it sounds a bit like premature
optimization. Not to mention that most of the projects
I have worked on don't have documentation nearly as
thorough or complete or up to date as the holy standard
library. In my experience causing a hard failure is a
better way to go (exception) -- unless profiling tells
you there is a performance problem, in which case
considering the "documented undefined behavior" route
may be justified.
Jul 22 '05 #11

P: n/a
JKop wrote:
Take a class like the following:

class Finger
{
public:

double length;
}
I'm writing reusable code and, being dictator, I dictate that "length"
cannot be negative. The following would be perfect:

unsigned double length;

But ofcourse doesn't compile.
So... I've come up with 3 potential solutions: A1 A2 B .
A) Create 2 separate member functions, GetLength and SetLength. SetLength
will reject negative numbers. When supplied with a negative number it will:
A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined behaviour if length is
set to a negative number.

Which would you suggest? Any other suggestions?
I myself am leaning toward B.
Thanks
-JKop


From an alternative perspective, define length in terms of the
smallest unit, then use an unsigned long or unsigned integer.
For example, one might use millimeters for length:
class Finger
{
unsigned int length; // in millimeters.
};

To get more pedantic, one might employ a template property
for the unit of measurement.
--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #12

P: n/a
template<class Class>
Class GeneratePositive(const Class& object)
{
return ( (object > 0) ? object : -object );
}
-JKop
Jul 22 '05 #13

P: n/a
"JKop" <NU**@NULL.NULL> wrote in message news:wFluc.911
template<class Class>
Class GeneratePositive(const Class& object)
{
return ( (object > 0) ? object : -object );
}


This is a fine solution for a certain problem. But most times I want the
program to error out when I give in wrong input, not to correct my wrong
input. This keeps the logic in my own code clear, which helps understanding
and maintaining the code.

Though to make it general, should we replace the "0" in object>0 with
"Class()"? A generic class may not have a conversion from zero as an
integer to a Class object, namely an implicit constructor Class::Class().
Jul 22 '05 #14

P: n/a
In article <_u***************@news.indigo.ie>, JKop <NU**@NULL.NULL>
wrote:
Take a class like the following:

class Finger
{
public:

double length;
}
I'm writing reusable code and, being dictator, I dictate that "length"
cannot be negative. The following would be perfect:

unsigned double length;

But ofcourse doesn't compile.
So... I've come up with 3 potential solutions: A1 A2 B .
A) Create 2 separate member functions, GetLength and SetLength. SetLength
will reject negative numbers. When supplied with a negative number it will:
A1) Throw an exception
A2) Return a false boolean value indicating failure

B) Just document that the code will have undefined behaviour if length is
set to a negative number.

Which would you suggest? Any other suggestions?


As with any other interface question, what would be easer for the
client? If the client code isn't any different no matter what you
choose, then choose the one that is easiest to implement (ie 'B'.)
At the very least, make sure that the behavior is defined in the debug
version of the program...

class Finger {
double _length;
public:
double length() { return _length; }
void length( double l ) { assert( l >= 0 ); _length = l; }
};

This is what I would recomend.
Jul 22 '05 #15

P: n/a


Another idea:

template<class Class> class Unsigned
{
private:

Class object;
public:

operator Class(void)
{
return object;
}

Class& operator=(const Class& in_object)
{
return ( object = ( (in_object > 0) ? in_object : -in_object) ) ;
}
};
int main(void)
{
Unsigned<double> diameter;

FunctionThatTakesADouble(diameter);

return 0;
}

One problem though is in specifying arguments to the constructor, and
accessing member functions and member variables. Then I considered the
following:


template<class Class> class Unsigned : public Class
{
Class& operator=(const Class& in_object)
{
return ( object = ( (in_object > 0) ? in_object : -in_object) ) ;
}
};

But then ofcourse, C++ limits the programmer from inheriting from intrinsic
types. Also, the operator= of the base class will have to be virtual.
Any thoughts?
-JKop
Jul 22 '05 #16

P: n/a
JKop posted:
Also, the operator= of the base class will have to be virtual.

Wrong about that.
-JKop
Jul 22 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.