Why are the min and max values for a particular numeric type implemented as functions?


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
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::eek: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.
 
Ad

Advertisements

H

Howard Hinnant

"Vijai Kalyan said:
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?

This is the unfortunate result of the fact that floating point constants
can't be defined in a class the way integral constants can, and
numeric_limits handles floating point types as well.

Yes, your compiler reflects the standard.

-Howard
 

Top