As in the title. As an exercise, I wanted to create an int that would enforce constraints on its value and would disallow being set to values outside its specified range.
Here is how I tried to approach this:
#include <cassert>
#include <cstdint>
#include <iostream>
using namespace std;
int main();
template<typename valtype, valtype minval, valtype maxval>
class ConstrainedValue
{
valtype val;
static bool checkval (valtype val)
{
return minval <= val && val <= maxval;
}
public:
ConstrainedValue() : val{minval} // so that we're able to write ConstrainedValue i;
{
assert(checkval(val));
}
ConstrainedValue(valtype val) : val{val}
{
assert(checkval(val));
}
ConstrainedValue &operator = (valtype val)
{
assert(checkval(val));
this->val = val;
return *this;
}
operator const valtype&() // Not needed here but can be; safe since it returns a const reference
{
return val;
}
friend ostream &operator << (ostream& out, const ConstrainedValue& v) // Needed because otherwise if valtype is char the output could be bad
{
out << +v.val;
return out;
}
friend istream &operator >> (istream& in, ConstrainedValue& v) // this is horrible ugly; I'd love to know how to do it better
{
valtype hlp;
auto hlp2 = +hlp;
in >> hlp2;
assert(checkval(hlp2));
v.val = hlp2;
return in;
}
};
int main()
{
typedef ConstrainedValue<uint_least8_t, 0, 100> ConstrainedInt;
ConstrainedInt i;
cin >> i;
cout << i;
return 0;
}
The problem is that... this is not working. If this custom integer is given values that overflow its underlying type it just sets erroneous values.
For example, let's assume that we have range constraints of [0; 100] and the underlying type is uint_least8_t, as in the example above. uint_least8_t evaluates to char or unsigned char, I'm not sure which. Let's try feeding this program with different values:
10
10
Nice. Works.
101
test: test.cpp:52: std::istream& operator>>(std::istream&, ConstrainedValue<unsigned int, 0u, 100u>&): Assertion `checkval(hlp2)' failed.
Aborted
Haha! Exactly what I wanted.
But:
257
1
Yeah. Overflow, truncate, wrong value, failed to check range correctly.
How to fix this problem?