V
Vijai Kalyan
Oops, maybe that is the standard. I don't have a copy unfortunately,
but here goes. I was experimenting and wrote the following code:
#include <limits.h>
#include <stdexcept>
#include <sstream>
namespace exceptions
{
class out_of_range : public std::exception
{
std::string m_msg;
protected:
out_of_range const& operator = (out_of_range const&);
public:
out_of_range(int p_min, int p_max, int p_value)
{
std::stringstream strbuf;
strbuf << "The value " << p_value << " is not in the
range [" << p_min << ", " << p_max << "].";
m_msg = strbuf.str();
}
out_of_range(out_of_range const& src)
{
m_msg = src.m_msg;
}
char const* what() const
{
return m_msg.c_str();
}
};
};
template
<
int t_Min,
int t_Max,
bool t_Validate,
bool t_useExceptionsstruct IntegerValidator
{
bool IsInRange(int value)
{
return true;
}
};
template
<
int t_Min,
int t_Max
bool IsInRange(int value)
{
return ((value <= t_Max) && (value >= t_Min));
}
};
template
<
int t_Min,
int t_Max
bool IsInRange(int value)
{
if(!::IntegerValidator<t_Min, t_Max, true,
false>::IsInRange(value))
{
throw exceptions:
ut_of_range(t_Min, t_Max, value);
}
return true;
}
};
template
<
int t_Min = INT_MIN,
int t_Max = INT_MAX,
bool t_Validate = true,
bool t_useExceptions = falseclass IntegerAttribute : public IntegerValidator<t_Min, t_Max,
t_Validate, t_useExceptions>
{
int m_value;
bool m_valid;
protected:
void SetValue(int p_value)
{
if(IsInRange(p_value))
{
m_value = p_value;
m_valid = true;
}
}
public:
IntegerAttribute() : m_value(0), m_valid(true)
{
}
explicit IntegerAttribute(int p_value) : m_value(0),
m_valid(false)
{
SetValue(p_value);
}
IntegerAttribute const& operator = (int p_value)
{
SetValue(p_value);
return *this;
}
IntegerAttribute const& operator = (IntegerAttribute const&
p_src)
{
SetValue(p_src.m_value);
}
operator int () const
{
return m_value;
}
};
#endif // end IntegerAttribute.h
just for fun. Here are now a few particular instantiations that I
tried:
typedef IntegerAttribute<0> PositiveInteger;
typedef IntegerAttribute<INT_MIN, 0> NegativeInteger;
typedef IntegerAttribute<0, INT_MAX, true, true> PositiveIntegerEx;
typedef IntegerAttribute<INT_MIN, 0, true, true> NegativeIntegerEx;
IMHO, I had to mix C style type ranges with C++. Shouldn't I ideally,
IMHO, have used
typedef IntegerAttribute<0> PositiveInteger;
typedef IntegerAttribute<std::numeric_limits<int>::min, 0>
NegativeInteger;
typedef IntegerAttribute<0, std::numeric_limits<int>::max, true, true>
PositiveIntegerEx;
typedef IntegerAttribute<std::numeric_limits<int>::min, 0, true, true>
NegativeIntegerEx;
instead. I cannot however do that because the above instantiations
require a compile time constant and min and max actually are functions.
Is this good? (Not from a style perspective, but from a usability
perspective.) Or am I missing something here?
Ultimately, anyway, in the particular compiler I am using the functions
min () and max() are anyway implemented as follows:
static _Ty (__CRTDECL min)() _THROW0()
{ // return minimum value
return (INT_MIN);
}
static _Ty (__CRTDECL max)() _THROW0()
{ // return maximum value
return (INT_MAX);
}
regards,
-vijai.
but here goes. I was experimenting and wrote the following code:
#include <limits.h>
#include <stdexcept>
#include <sstream>
namespace exceptions
{
class out_of_range : public std::exception
{
std::string m_msg;
protected:
out_of_range const& operator = (out_of_range const&);
public:
out_of_range(int p_min, int p_max, int p_value)
{
std::stringstream strbuf;
strbuf << "The value " << p_value << " is not in the
range [" << p_min << ", " << p_max << "].";
m_msg = strbuf.str();
}
out_of_range(out_of_range const& src)
{
m_msg = src.m_msg;
}
char const* what() const
{
return m_msg.c_str();
}
};
};
template
<
int t_Min,
int t_Max,
bool t_Validate,
bool t_useExceptionsstruct IntegerValidator
{
bool IsInRange(int value)
{
return true;
}
};
template
<
int t_Min,
int t_Max
{struct IntegerValidator<t_Min, t_Max, true, false>
bool IsInRange(int value)
{
return ((value <= t_Max) && (value >= t_Min));
}
};
template
<
int t_Min,
int t_Max
{struct IntegerValidator<t_Min, t_Max, true, true> : public IntegerValidator<t_Min, t_Max, true, false>
bool IsInRange(int value)
{
if(!::IntegerValidator<t_Min, t_Max, true,
false>::IsInRange(value))
{
throw exceptions:
}
return true;
}
};
template
<
int t_Min = INT_MIN,
int t_Max = INT_MAX,
bool t_Validate = true,
bool t_useExceptions = falseclass IntegerAttribute : public IntegerValidator<t_Min, t_Max,
t_Validate, t_useExceptions>
{
int m_value;
bool m_valid;
protected:
void SetValue(int p_value)
{
if(IsInRange(p_value))
{
m_value = p_value;
m_valid = true;
}
}
public:
IntegerAttribute() : m_value(0), m_valid(true)
{
}
explicit IntegerAttribute(int p_value) : m_value(0),
m_valid(false)
{
SetValue(p_value);
}
IntegerAttribute const& operator = (int p_value)
{
SetValue(p_value);
return *this;
}
IntegerAttribute const& operator = (IntegerAttribute const&
p_src)
{
SetValue(p_src.m_value);
}
operator int () const
{
return m_value;
}
};
#endif // end IntegerAttribute.h
just for fun. Here are now a few particular instantiations that I
tried:
typedef IntegerAttribute<0> PositiveInteger;
typedef IntegerAttribute<INT_MIN, 0> NegativeInteger;
typedef IntegerAttribute<0, INT_MAX, true, true> PositiveIntegerEx;
typedef IntegerAttribute<INT_MIN, 0, true, true> NegativeIntegerEx;
IMHO, I had to mix C style type ranges with C++. Shouldn't I ideally,
IMHO, have used
typedef IntegerAttribute<0> PositiveInteger;
typedef IntegerAttribute<std::numeric_limits<int>::min, 0>
NegativeInteger;
typedef IntegerAttribute<0, std::numeric_limits<int>::max, true, true>
PositiveIntegerEx;
typedef IntegerAttribute<std::numeric_limits<int>::min, 0, true, true>
NegativeIntegerEx;
instead. I cannot however do that because the above instantiations
require a compile time constant and min and max actually are functions.
Is this good? (Not from a style perspective, but from a usability
perspective.) Or am I missing something here?
Ultimately, anyway, in the particular compiler I am using the functions
min () and max() are anyway implemented as follows:
static _Ty (__CRTDECL min)() _THROW0()
{ // return minimum value
return (INT_MIN);
}
static _Ty (__CRTDECL max)() _THROW0()
{ // return maximum value
return (INT_MAX);
}
regards,
-vijai.