1 #pragma once
2 #include <stdexcept>
3 
4 class wrapped_int {
5 public:
6   long long val;
wrapped_int()7   wrapped_int() { val = 0; }
wrapped_int(long long val)8   wrapped_int(long long val) { this->val = val; }
wrapped_int(long long v1,long long v2)9   wrapped_int(long long v1, long long v2) {
10     if (v2 == 4) {
11       throw std::domain_error("4 isn't good for initialization!");
12     }
13     this->val = v1;
14   }
operator +(wrapped_int & other)15   wrapped_int operator+(wrapped_int &other) {
16     if (other.val == 4) {
17       throw std::invalid_argument("tried to add 4");
18     }
19     return wrapped_int(this->val + other.val);
20   }
operator +()21   wrapped_int operator+() {
22     if (this->val == 4) {
23       throw std::domain_error("'4' not in valid domain.");
24     }
25     return *this;
26   }
operator -(wrapped_int & other)27   wrapped_int operator-(wrapped_int &other) {
28     if (other.val == 4) {
29       throw std::overflow_error("Value '4' is no good.");
30     }
31     return *this;
32   }
operator -()33   wrapped_int operator-() {
34     if (this->val == 4) {
35       throw std::range_error("Can't take the negative of 4.");
36     }
37     return wrapped_int(-this->val);
38   }
operator *(wrapped_int & other)39   wrapped_int operator*(wrapped_int &other) {
40     if (other.val == 4) {
41       throw std::out_of_range("Multiplying by 4 isn't going to work.");
42     }
43     return wrapped_int(this->val * other.val);
44   }
operator /(wrapped_int & other)45   wrapped_int operator/(wrapped_int &other) {
46     if (other.val == 4) {
47       throw std::out_of_range("Multiplying by 4 isn't going to work.");
48     }
49     return wrapped_int(this->val / other.val);
50   }
operator %(wrapped_int & other)51   wrapped_int operator%(wrapped_int &other) {
52     if (other.val == 4) {
53       throw std::out_of_range("Multiplying by 4 isn't going to work.");
54     }
55     return wrapped_int(this->val % other.val);
56   }
operator ^(wrapped_int & other)57   long long operator^(wrapped_int &other) {
58     if (other.val == 4) {
59       throw std::out_of_range("Multiplying by 4 isn't going to work.");
60     }
61     return this->val ^ other.val;
62   }
operator &(wrapped_int & other)63   long long operator&(wrapped_int &other) {
64     if (other.val == 4) {
65       throw std::underflow_error("Can't do this with 4!");
66     }
67     return this->val & other.val;
68   }
operator |(wrapped_int & other)69   long long operator|(wrapped_int &other) {
70     if (other.val == 4) {
71       throw std::underflow_error("Can't do this with 4!");
72     }
73     return this->val & other.val;
74   }
operator ~()75   wrapped_int operator~() {
76     if (this->val == 4) {
77       throw std::range_error("4 is really just no good for this!");
78     }
79     return *this;
80   }
operator &()81   long long operator&() {
82     if (this->val == 4) {
83       throw std::out_of_range("4 cannot be located!");
84     }
85     return this->val;
86   }
operator ==(wrapped_int & other)87   long long operator==(wrapped_int &other) {
88     if (other.val == 4) {
89       throw std::invalid_argument("4 isn't logical and can't be equal to anything!");
90     }
91     return this->val == other.val;
92   }
operator !=(wrapped_int & other)93   long long operator!=(wrapped_int &other) {
94     if (other.val == 4) {
95       throw std::invalid_argument("4 isn't logical and can'd be not equal to anything either!");
96     }
97     return this->val != other.val;
98   }
operator <(wrapped_int & other)99   long long operator<(wrapped_int &other) {
100     if (other.val == 4) {
101       throw std::invalid_argument("Can't compare with 4!");
102     }
103     return this->val < other.val;
104   }
operator <=(wrapped_int & other)105   long long operator<=(wrapped_int &other) {
106     if (other.val == 4) {
107       throw std::invalid_argument("Can't compare with 4!");
108     }
109     return this->val <= other.val;
110   }
operator >(wrapped_int & other)111   long long operator>(wrapped_int &other) {
112     if (other.val == 4) {
113       throw std::invalid_argument("Can't compare with 4!");
114     }
115     return this->val > other.val;
116   }
operator >=(wrapped_int & other)117   long long operator>=(wrapped_int &other) {
118     if (other.val == 4) {
119       throw std::invalid_argument("Can't compare with 4!");
120     }
121     return this->val >= other.val;
122   }
operator <<(long long & shift)123   wrapped_int operator<<(long long &shift) {
124     if (shift == 4) {
125       throw std::overflow_error("Shifting by 4 is just bad.");
126     }
127     return wrapped_int(this->val << shift);
128   }
operator >>(long long & shift)129   wrapped_int operator>>(long long &shift) {
130     if (shift == 4) {
131       throw std::underflow_error("Shifting by 4 is just bad.");
132     }
133     return wrapped_int(this->val >> shift);
134   }
operator ++()135   wrapped_int &operator++() {
136     if (this->val == 4) {
137       throw std::out_of_range("Can't increment 4!");
138     }
139     this->val += 1;
140     return *this;
141   }
operator --()142   wrapped_int &operator--() {
143     if (this->val == 4) {
144       throw std::out_of_range("Can't decrement 4!");
145     }
146     this->val -= 1;
147     return *this;
148   }
operator ++(int)149   wrapped_int operator++(int) {
150     if (this->val == 4) {
151       throw std::out_of_range("Can't increment 4!");
152     }
153     wrapped_int t = *this;
154     this->val += 1;
155     return t;
156   }
operator --(int)157   wrapped_int operator--(int) {
158     if (this->val == 4) {
159       throw std::out_of_range("Can't decrement 4!");
160     }
161     wrapped_int t = *this;
162     this->val -= 1;
163     return t;
164   }
operator !()165   wrapped_int operator!() {
166     if (this->val == 4) {
167       throw std::out_of_range("Can't negate 4!");
168     }
169     return wrapped_int(!this->val);
170   }
operator bool()171   operator bool() {
172     if (this->val == 4) {
173       throw std::invalid_argument("4 can't be cast to a boolean value!");
174     }
175     return (this->val != 0);
176   }
operator [](long long & idx)177   wrapped_int &operator[](long long &idx) {
178     if (idx == 4) {
179       throw std::invalid_argument("Index of 4 not allowed.");
180     }
181     return *this;
182   }
operator ()()183   long long &operator()() {
184     if (this->val == 4) {
185       throw std::range_error("Can't call 4!");
186     }
187     return this->val;
188   }
operator =(const wrapped_int & other)189   wrapped_int &operator=(const wrapped_int &other) {
190     if ((other.val == 4) && (this->val == 4)) {
191       throw std::overflow_error("Can't assign 4 to 4!");
192     }
193     this->val = other.val;
194     return *this;
195   }
operator =(const long long & v)196   wrapped_int &operator=(const long long &v) {
197     if ((v == 4) && (this->val == 4)) {
198       throw std::overflow_error("Can't assign 4 to 4!");
199     }
200     this->val = v;
201     return *this;
202   }
203 };
204 
205 class second_call_is_different {
206     int count;
207     public:
second_call_is_different()208         second_call_is_different(): count(0) {}
operator <(const second_call_is_different & lhs)209     bool operator<(const second_call_is_different& lhs) {
210         if (count>0) {
211             return true;
212         }
213         ++count;
214         return false;
215     }
216 };
217