473,413 Members | 1,854 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,413 software developers and data experts.

Creating a number with a range

Hi,

Say I have:
class Latitude
{
friend bool operator==(const Latitude& lhs, const Latitude& rhs);
friend bool operator<(const Latitude& lhs, const Latitude& rhs);
friend std::ostream& operator<<(std::ostream& os, const Latitude& l);

public:
explicit Latitude(double latitude);
double latitude() const { return latitude_; }

private:
double latitude_;
};
So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.

Now, I've got to do the same with Longitude and Altitude. They're all
kinda the same, except that Longitude can range from -180 to 180, and
Altitude doesn't really have a limit (I guess its the limit on what a
double can hold).

How can I consolidate this logic? Templates? Inheritance? Or am I going
about this completely wrong?

Joe
Aug 11 '06 #1
7 2322
Joe Van Dyk wrote:
Hi,

Say I have:
class Latitude
{
friend bool operator==(const Latitude& lhs, const Latitude& rhs);
friend bool operator<(const Latitude& lhs, const Latitude& rhs);
friend std::ostream& operator<<(std::ostream& os, const Latitude& l);

public:
explicit Latitude(double latitude);
double latitude() const { return latitude_; }

private:
double latitude_;
};
So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.

Now, I've got to do the same with Longitude and Altitude. They're all
kinda the same, except that Longitude can range from -180 to 180, and
Altitude doesn't really have a limit (I guess its the limit on what a
double can hold).

How can I consolidate this logic? Templates? Inheritance? Or am I going
about this completely wrong?
One more or less elegant way to approach this might be to use a policy
for validation:

-- BEGIN EXAMPLE CODE --
// DerangedDouble.h
#include <stdexcept>

template < class ValidationPolicy >
class DerangedDouble
{
public :
DerangedDouble( double d )
: d_(d)
{
if (!ValidationPolicy::validate(d))
throw std::range_error("value out of range!");
else
{ /* all is well */ }
}

private :
double d_;
};

// ValidationPolicies.h
struct LatitudeValidation
{
static bool validate(double d)
{
return d < 90 && d -90;
}
};

struct LongitudeValidation
{
static bool validate(double d)
{
return d >= -180 && d <= 180;
}
};

struct AltitudeValidation
{
static bool validate(double d)
{
return d >= 0;
}
};

// test.cpp
#include "DerangedDouble.h"
#include "ValidationPolicies.h"

typedef DerangedDouble< LongitudeValidation Longitude;
typedef DerangedDouble< LatitudeValidation Latitude;
typedef DerangedDouble< AltitudeValidation Altitude;

int main()
{
Longitude longitude(0);
Latitude latitude(0);
Altitude altitude(0);

return 0;
}
--- END EXAMPLE CODE ---
The fun with that is that you can easily make another class, say
"Temperature" with a TemperatureValidation policy.
Have a look at Andrei Alexandrescu's book "Modern C++ Design" for more
extensive information on policies :)

rlc

Aug 11 '06 #2
On Thu, 10 Aug 2006 20:54:42 -0700, blytkerchan wrote:
Joe Van Dyk wrote:
>Hi,

Say I have:
class Latitude
{
friend bool operator==(const Latitude& lhs, const Latitude& rhs);
friend bool operator<(const Latitude& lhs, const Latitude& rhs);
friend std::ostream& operator<<(std::ostream& os, const Latitude& l);

public:
explicit Latitude(double latitude);
double latitude() const { return latitude_; }

private:
double latitude_;
};
So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.

Now, I've got to do the same with Longitude and Altitude. They're all
kinda the same, except that Longitude can range from -180 to 180, and
Altitude doesn't really have a limit (I guess its the limit on what a
double can hold).

How can I consolidate this logic? Templates? Inheritance? Or am I going
about this completely wrong?
One more or less elegant way to approach this might be to use a policy
for validation:

-- BEGIN EXAMPLE CODE --
// DerangedDouble.h
#include <stdexcept>

template < class ValidationPolicy >
class DerangedDouble
{
public :
DerangedDouble( double d )
: d_(d)
{
if (!ValidationPolicy::validate(d))
throw std::range_error("value out of range!");
else
{ /* all is well */ }
}

private :
double d_;
};

// ValidationPolicies.h
struct LatitudeValidation
{
static bool validate(double d)
{
return d < 90 && d -90;
}
};

struct LongitudeValidation
{
static bool validate(double d)
{
return d >= -180 && d <= 180;
}
};

struct AltitudeValidation
{
static bool validate(double d)
{
return d >= 0;
}
};

// test.cpp
#include "DerangedDouble.h"
#include "ValidationPolicies.h"

typedef DerangedDouble< LongitudeValidation Longitude;
typedef DerangedDouble< LatitudeValidation Latitude;
typedef DerangedDouble< AltitudeValidation Altitude;

int main()
{
Longitude longitude(0);
Latitude latitude(0);
Altitude altitude(0);

return 0;
}
--- END EXAMPLE CODE ---
The fun with that is that you can easily make another class, say
"Temperature" with a TemperatureValidation policy.
Have a look at Andrei Alexandrescu's book "Modern C++ Design" for more
extensive information on policies :)

rlc
Thanks! I was thinking something along those lines. Why is
AltitudeValidation::validate static?

Joe

Aug 11 '06 #3
In article <pa****************************@boeing.com>,
jo********@boeing.com says...

[ ... ]
So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.
You've gotten (at least) one suggestion already, but IMO, using a policy
to do nothing more than specify a range is overkill. I've posted this a
few times before, but I guess once more won't hurt too much:

#include <exception>
#include <iostream>
#include <functional>

template <class T, T lower, T upper, class less=std::less<T
class bounded {
T val;

static bool check(T const &value) {
return less()(value, lower) || less()(upper, value);
}

public:
bounded() : val(lower) { }

bounded(T const &v) {
if (check(v))
throw std::domain_error("out of range");
val = v;
}

bounded(bounded const &init) : val(init.v) {}

bounded &operator=(T const &v) {
if (check(v))
throw std::domain_error("Out of Range");
val = v;
return *this;
}

operator T() const { return val; }

friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >temp;

if (check(temp))
is.setstate(std::ios::failbit);
b.val = temp;
return is;
}
};

It might make sense to use a policy template, but the policy would be to
govern what happens when you attempt to assign an out-of-range value. As
it stands right now, this throws an exception, but for different
circumstances, it might be reasoanble to reduce the new value modulo the
range (or upper value of the range), or simply fail the assignment,
leaving the variable unaltered. I've never had a need for that, however,
so I've never gotten beyond the point of mentioning it in a post or two.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 11 '06 #4
On Fri, 11 Aug 2006 14:09:36 +0000, Joe Van Dyk wrote:
On Thu, 10 Aug 2006 20:54:42 -0700, blytkerchan wrote:
>Joe Van Dyk wrote:
>>Hi,

Say I have:
class Latitude
{
friend bool operator==(const Latitude& lhs, const Latitude& rhs);
friend bool operator<(const Latitude& lhs, const Latitude& rhs);
friend std::ostream& operator<<(std::ostream& os, const Latitude& l);

public:
explicit Latitude(double latitude);
double latitude() const { return latitude_; }

private:
double latitude_;
};
So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.

Now, I've got to do the same with Longitude and Altitude. They're all
kinda the same, except that Longitude can range from -180 to 180, and
Altitude doesn't really have a limit (I guess its the limit on what a
double can hold).

How can I consolidate this logic? Templates? Inheritance? Or am I going
about this completely wrong?
One more or less elegant way to approach this might be to use a policy
for validation:

-- BEGIN EXAMPLE CODE --
// DerangedDouble.h
#include <stdexcept>

template < class ValidationPolicy >
class DerangedDouble
{
public :
DerangedDouble( double d )
: d_(d)
{
if (!ValidationPolicy::validate(d))
throw std::range_error("value out of range!");
else
{ /* all is well */ }
}

private :
double d_;
};

// ValidationPolicies.h
struct LatitudeValidation
{
static bool validate(double d)
{
return d < 90 && d -90;
}
};

struct LongitudeValidation
{
static bool validate(double d)
{
return d >= -180 && d <= 180;
}
};

struct AltitudeValidation
{
static bool validate(double d)
{
return d >= 0;
}
};

// test.cpp
#include "DerangedDouble.h"
#include "ValidationPolicies.h"

typedef DerangedDouble< LongitudeValidation Longitude;
typedef DerangedDouble< LatitudeValidation Latitude;
typedef DerangedDouble< AltitudeValidation Altitude;

int main()
{
Longitude longitude(0);
Latitude latitude(0);
Altitude altitude(0);

return 0;
}
--- END EXAMPLE CODE ---
The fun with that is that you can easily make another class, say
"Temperature" with a TemperatureValidation policy.
Have a look at Andrei Alexandrescu's book "Modern C++ Design" for more
extensive information on policies :)

rlc

Thanks! I was thinking something along those lines. Why is
AltitudeValidation::validate static?

Joe
Oh, nevermind, I get it. That make it a class function, or whatever the
correct terminology is.

template<class ValidationPolicy>
class BaseNumber
{
public:
explicit BaseNumber(double val)
: value_(0)
{
if (!ValidationPolicy::validate(val))
{
throw std::range_error(std::string("Needs to be between "
+ ValidationPolicy::min + " and "
+ ValidationPolicy::max));
}
value_ = val;
}

double value() const { return value_; }

private:
double value_;
};

struct BaseValidation
{
static double max, min;
static bool validate(double val)
{
return val >= min && val <= max;
}
};

struct AltitudeValidation : public BaseValidation
{
AltitudeValidation() { max = 10000000; min = 0; }
};
typedef BaseNumber<AltitudeValidationAltitude;
It's not working, since I can't access max and min inside
BaseValidation::validate.

Is something like the above possible? Or am I completely going in the
wrong direction?

Joe

Aug 11 '06 #5
Jerry Coffin wrote:
In article <pa****************************@boeing.com>,
jo********@boeing.com says...

[ ... ]
>So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.

You've gotten (at least) one suggestion already, but IMO, using a policy
to do nothing more than specify a range is overkill. I've posted this a
few times before, but I guess once more won't hurt too much:

#include <exception>
#include <iostream>
#include <functional>

template <class T, T lower, T upper, class less=std::less<T
class bounded {
But T would need to be an integral type here making it useless
for the OP.

Aug 11 '06 #6
On Fri, 11 Aug 2006 20:21:45 +0200, Markus Schoder wrote:
Jerry Coffin wrote:
>In article <pa****************************@boeing.com>,
jo********@boeing.com says...

[ ... ]
>>So, it's essentially a wrapper around a double. The constructor enforces
that the latitude can't be less than -90 or greater than 90. Comparison
operators do the comparison of the double.

You've gotten (at least) one suggestion already, but IMO, using a policy
to do nothing more than specify a range is overkill. I've posted this a
few times before, but I guess once more won't hurt too much:

#include <exception>
#include <iostream>
#include <functional>

template <class T, T lower, T upper, class less=std::less<T
class bounded {

But T would need to be an integral type here making it useless
for the OP.
As T can't be a floating point type, right? Is that going to be fixed in
an upcoming standard?

Aug 11 '06 #7
In article <44***********************@newsspool2.arcor-online.net>,
a3*************@yahoo.de says...

[ ... ]
But T would need to be an integral type here making it useless
for the OP.
Sorry -- I'd meant to mention that (at least IMO) most things that deal
with hard boundaries probably shouldn't be using floating point in the
first place. Floating point and "hard" are almost mutually exclusive
concepts. A floating point number usually needs to be viewed as a rather
soft, imprecise kind of thing, so if you're dealing with hard limits,
chances are you shouldn't be using a floating point number.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 14 '06 #8

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

Similar topics

5
by: Minho Chae | last post by:
Hello, python lovers!! I'm trying to create combinations of sequences. For example, if the sequence is 'acgt' and the length is 8, then I would like to have 4^8 results such as 'aaaaaaaa',...
17
by: Ange T | last post by:
Hi there, I'm having pain with the VB behind an Access form. The form is used to create reports in Excel based on the details entered in the form. This has always worked without error on my...
3
by: Robin S. | last post by:
This is more of a structural question (me: newbie) as opposed to specific coding. Please be patient... I'm making a database for the small company I work for. It will be to add and edit products...
3
by: m3ckon | last post by:
Hi there, I can succesfully create a word doc from my asp.net page, but I have 2 issues I need to resolve in order to use it in my app: 1) Creating a table: I seem unable to create a table,...
4
by: Mahesh S | last post by:
Hi I would like to have an attribute that would store an integer or float range (say 6 to 10). Is it possible to have both the lower and upper limit specified in a single field? Thanks...
5
by: apartain | last post by:
My database is based on Work Order Numbers. If an employee enters labor, they must include the WO Number for it. Equipment, subcontractors, per diem and materials all must also have a WO number. ...
2
by: joebenjamin | last post by:
I am trying to write a program that will generate 100 random numbers between 1 and 50. Using these numbers, generate a list that will tell the number of random numbers that fell between 1-5, 6-10,...
0
by: helraizer1 | last post by:
Hi folks, I have made a ledger sub in Excel. The task is to create a spreadsheet solution for a foreign exchange bureau so each transaction that happens it adds the details to a ledger sheet. ...
2
by: uamusa | last post by:
I am Dynamically generating a proposal(report) in MS Word. By default the Paragraph Alignment is "Left". For the First 6 Paragraphs I set the Alignment to "Center", and then when attempting to...
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
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.