Just because you add identifiers for the values doesn't mean you have to use them... you can use Value(0)
, Value(2)
etc. if that's more convenient, but there is a danger: enum
doesn't restrict the value stored to those listed... e.g. it won't protect you against Value(3)
.
Inside structs/classes you can use bit fields to restrict the storage used for numbers, but even then:
- the range has to correspond to either the signed or unsigned values possible in the number of bits requested
- attempts to assign other values will result in high order bits being removed rather than any kind of compile- or run-time error
If your intention is to create a distinct type that enforces a restricted values 0 through 2, then you need a class with specialised constructor and assignment operators:
template <int MIN, int MAX>
class Bound
{
public:
explicit Bound(int n) { *this = n; }
Bound& operator=(int n)
{
if (n < MIN or n > MAX)
throw std::runtime_error("out of bounds");
n_ = n;
return *this;
}
Bound& operator+=(int n) { *this = n_ + n; }
// should "+" return int or Bound? entirely usage dependent...
Bound operator+(int n) { return Bound(n_ + n); }
// -=, -, *=, *, /=, /, %=, %, bitwise ops, pre/post ++/-- etc...
operator int() const { return n_; }
private:
int n_;
};