0

I have to write this Course class, which has elements like room, day_of_week and so on.

Each of them must be declared in a specific range for the course to be valid.

For example, day_of_week must be an integer between 1 and 6, and room must be an integer between 1 and 599.

My question is, is there a way to write my constructor so that when I initialize an object with invalid data it will not compile.

Putting it in another perspective, is there a way to declare the range of my data members in the constructor or in the class declaration.

Sorry for the long read any help is welcomed.

barak manos
  • 29,648
  • 10
  • 62
  • 114
user3144334
  • 135
  • 1
  • 1
  • 9
  • No, while [`enum class`es](http://en.cppreference.com/w/cpp/language/enum) might help, there is no standard data type for integers with arbitrary range restrictions. – danielschemmel Apr 28 '14 at 18:48
  • 2
    The only way to have compile-time checking is to make the variables template arguments. For exceptional circumstances use exceptions. – Some programmer dude Apr 28 '14 at 18:49
  • 1
    Take a look at http://stackoverflow.com/questions/148511/limiting-range-of-value-types-in-c because this type of question has been asked before. If you are reading inputs from a stream or a file then compile time restrictions would not help you very much. Keep variables private and restrict mutation within interfaces. – shawn1874 Apr 28 '14 at 19:11
  • @shawn1874 Thanks for that it's an interesting read. – user3144334 Apr 28 '14 at 19:20

1 Answers1

2

No, C++ does not come with a way to do range checking, you could however implement your own number class which overloads the assignment and arithmetic operators:

#include <cassert>
template<int lower, int upper>
class RangedNumber{
public:
    RangedNumber(int value):value(value){
        test();
    }

    RangedNumber(const RangedNumber& r):value(r.value){}

    RangedNumber& operator+=(int i){
        value += i;
        test();
        return *this;
    }

    RangedNumber operator+(int i) const{
        RangedNumber r(*this);
        return r += i;
    }

    RangedNumber& operator-=(int i){
        value -= i;
        test();
        return *this;
    }

    RangedNumber operator-(int i) const{
        RangedNumber r(*this);
        return r -= i;
    }

    int get() const {
        return value;
    }
private:

    int value;
    void test(){
        if(value < lower || value >= upper) 
            throw std::out_of_range;
    }
};
niklasfi
  • 15,245
  • 7
  • 40
  • 54
  • Yes I also have to overload the >> operator. In the overloading when I check if the data is valid, if it turns out it is not, should I return 0 (this I think will stop the whole program) or something else to stop the cin process and move on to the next part ? – user3144334 Apr 28 '14 at 18:57
  • My above code is probably more of a proof of concept than something you should ship. I would actually raise an [exception](http://www.cplusplus.com/doc/tutorial/exceptions/) in the case that the number is out of range. – niklasfi Apr 28 '14 at 18:59
  • Yep i think it's too much work to write a template for every data members range. Sorry for asking it again but is there a way to break the input of an object if I find a broken condition while inputting it?for example if I input 700 for the value of room, press enter the input of this object would stop and the program will move to the next task ? – user3144334 Apr 28 '14 at 19:04
  • That seems like overkill to me, and I don't see how this is any better than just range checking and throwing from within a constructor by testing the built in type using user defined constants for the min and max. – shawn1874 Apr 28 '14 at 19:06
  • @user3144334 this is what exceptions are for. If you raise `std::out_of_range` in your `operator<<`, you could catch it in your `main` function or whatever calls the `operator<<` with a `try {} catch (std::out_of_range e) {}` block. – niklasfi Apr 28 '14 at 19:07
  • Your code allows the `value` to be modified even though the resulting operation could result in an out-of-range result. Perform the range check before modifying the value instead. – Void - Othman Apr 28 '14 at 20:25