C++ can do this very well, no eye bleed is involved.
type Age is new Natural range 0..150; using age = in_range<int, 0, 150>;
Not the end of the world(note C++ is a big language that changes a lot)
template<typename T, int min, int max> // probably not int for min/max, but whatever
class in_range {
...
};
which would be instantiated with `using <my_type_name> = ...;` and would have all the necessary operator overloads and checks. Still, it's only bringing in the runtime, not compile time, checks and can't be "turned off" (well, maybe
take a fourth boolean value and have two code paths everywhere that can be optimized down to one if you want to turn off the checks) like it can in Ada (whether that's a good idea or not depends on how well you've proved out your code). It's also introducing all the overhead of an object which isn't necessary in Ada.it's doable to have both compile-time and run-time checks:
https://gcc.godbolt.org/z/oT3adre86
some compile-time interval calculus library would enable more check and does not seem much harder to implement than a run-time one.
#include <stdexcept>
template <int min, int max>
class Range
{
public:
Range(int i): i(i)
{
if (i < min)
throw std::runtime_error("value lower than minimum " + std::to_string(min));
if (i > max)
throw std::runtime_error("value higher than maximum " + std::to_string(max));
}
int to_int() const { return i; };
private:
int i;
};
using Month = Range<1, 12>;
int main()
{
Month month(-1);
}
terminate called after throwing an instance of 'std::runtime_error'
what(): value lower than minimum 1