468,268 Members | 1,573 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,268 developers. It's quick & easy.

Ranged Integers

is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?

Sep 2 '07 #1
9 1377
In article <11**********************@o80g2000hse.googlegroups .com>,
fo*********@yahoo.com says...
is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?
This might fill the bill:

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

template <class T, class less=std::less<T
class bounded {
const T lower_, upper_;
T val_;

bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}

void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}

public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}

bounded(bounded const &init) { assign(init); }

bounded &operator=(T const &v) { assign(v); return *this; }

operator T() const { return val_; }

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

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

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 2 '07 #2
On Sep 3, 2:06 am, foothomp...@yahoo.com wrote:
is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?
Hi

I think the solution by Jerry is good and sophisticated. But a simpler
version of range concept that I usually use, is a simple rangle class
offered by Bjarne Stroustrup in his seminars:
// Range concept (for integers)
class Range { // simple value type
int value, low, high; // invariant: low <= value < high
check(int v) { if (!(low<=v && v<high)) throw Range_error(); }
public:
Range(int lo, int v, int hi) : low(lo), value(v), high(hi)
{ check(v); }
Range& operator=(const Range& a) { check(a.v); value = a.value;
return *this; }
Range& operator=(int a) { check(a); value = a; return *this; }
operator int() { return value; }
};

Regards,
Saeed Amrollahi

Sep 3 '07 #3
On Sep 3, 4:47 am, Jerry Coffin <jcof...@taeus.comwrote:
In article <1188774365.772466.314...@o80g2000hse.googlegroups .com>,
foothomp...@yahoo.com says...
is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?

This might fill the bill:

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

template <class T, class less=std::less<T
class bounded {
const T lower_, upper_;
T val_;

bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}

void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}

public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}

bounded(bounded const &init) { assign(init); }
doubt: for copy c'tor here, will the lower_ & upper_ get initialized?
bounded &operator=(T const &v) { assign(v); return *this; }

operator T() const { return val_; }

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

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

};

--
Later,
Jerry.

The universe is a figment of its own imagination.

Sep 3 '07 #4
bu******@googlemail.com wrote:
>[snip]

void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}

public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}

bounded(bounded const &init) { assign(init); }

doubt: for copy c'tor here, will the lower_ & upper_ get initialized?
No. Since lower_ and upper_ are declared const you cannot assign them any
values. However, you can initialize them in the copy-constructor, like so:

bounded(const bounded& init)
: lower_(init.lower_), upper_(init.upper_)
{assign(init); }

[snip]
Sep 3 '07 #5
On Sun, 2 Sep 2007 17:47:13 -0600, Jerry Coffin <jc*****@taeus.com>
wrote:
>In article <11**********************@o80g2000hse.googlegroups .com>,
fo*********@yahoo.com says...
>is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?

This might fill the bill:
<...>

Or, pressing it harder:

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

template <class T, T lower, T higher, class less=std::less<T
class bounded {
T val_;

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

void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}

public:
explicit bounded(T val) {assign(val);}

bounded() :val_(
less()(T(),lower)?lower:
less()(higher,T())?higher:T()) {}

bounded(bounded const &init):val_(init.val_) {}

template<T1,T1 other_lower,T1 other_higher,less1>
bounded(
bounded<T1,other_lower,other_higher,less1>
const &init) {assign(init.val_)}

bounded &operator=(T const &v) { assign(v); return *this; }

bounded &operator=(bounded const &v) {val_=v.val_; return *this;}

template<T1,T1 other_lower,T1 other_higher,less1>
bounded& operator=(
bounded<T1,other_lower,other_higher,less1>
const &v) {assign(v.val_)}

operator T() const { return val_; }

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

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

Just to have different types for different ranges, and faster
assignment/copy when maintining range.

Regards,

Zara
Sep 3 '07 #6
In article <11*********************@50g2000hsm.googlegroups.c om>,
bu******@googlemail.com says...

[ ... ]
bounded(bounded const &init) { assign(init); }

doubt: for copy c'tor here, will the lower_ & upper_ get initialized?
Oops -- no, they won't. That's definitely a bug -- thanks for pointing
it out.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 3 '07 #7
In article <qj********************************@4ax.com>,
me*****@dea.spamcon.org says...

[ ... ]
template <class T, T lower, T higher, class less=std::less<T
Yeah, I've played with one like that as well. As you note, it does
improve efficiency, and for the exact question that was asked, it works
quite well. The one major shortcoming is that it can't be applied to
floating point types.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 3 '07 #8
On Sep 3, 2:06 am, foothomp...@yahoo.com wrote:
is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?
template<typename Numeric,Numeric low,Numeric up>
struct bounded{
typedef Numeric value_type;
enum{lower=low,upper=up};//no runtime overhead
operator value_type&()const{return value;};
explicit bounded(const Numeric& i);
const value_type& operator=(const Numeric& r);
.....//etc
private:
Numeric value;
};

regards,
FM.

Sep 3 '07 #9
On Sep 3, 8:42 pm, terminator <farid.mehr...@gmail.comwrote:
On Sep 3, 2:06 am, foothomp...@yahoo.com wrote:
is there a simple integer type library around that behaves like normal
integers, i.e has all the same operations, but except the value can
only be in a specific range, like 0 to 100, and if the value is
outside of this range, it will throw an exception or assert fail?

template<typename Numeric,Numeric low,Numeric up>
struct bounded{
typedef Numeric value_type;
enum{lower=low,upper=up};//no runtime overhead
operator value_type&()const{return value;};
explicit bounded(const Numeric& i);
const value_type& operator=(const Numeric& r);
.....//etc
private:
Numeric value;

};

regards,
FM.
that works with integrals for none-integral numerics(float/double...):

template<typename Numeric,Numeric low,Numeric up>//no memory overhead
for bounds
struct bounded_real{
typedef Numeric value_type;
static const value_type& lower(){
static const value_type data=low;
};
static const value_type& upper(){
static const value_type data=up;
};
...//etc
};

Sep 3 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

29 posts views Thread by Chris Dutrow | last post: by
13 posts views Thread by Jeff Melvaine | last post: by
reply views Thread by christopher diggins | last post: by
4 posts views Thread by Neal Becker | last post: by
13 posts views Thread by Nicholas | last post: by
16 posts views Thread by aruna | last post: by
1 post views Thread by calvin | last post: by
7 posts views Thread by Girish Sahani | last post: by
reply views Thread by NPC403 | last post: by
reply views Thread by kermitthefrogpy | last post: by
reply views Thread by zattat | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.