Problem with overloading member functions

I have written a class like this:
1
2
3
4
5
class Foo {
public:
    void bar(const int&);
    void bar(const double&);
}

Recently, I changed the data type of one member variable from int to long, and now I want the member functions to take a double or a long. I tried doing this:
1
2
3
4
5
class Foo {
public:
    void bar(const long&);
    void bar(const double&);
}

But, when I call Foo::bar() with an integer (e.g. x.bar(1)), the compiler tells me that both of the overloads meet the specified type, and that it doesn't know to cast "10" into a long or double.
I tried to fix it by providing a void Foo::bar(const int&), and call Foo::bar(const long&) in it with the parameter casted to a long. It worked, but in my real code there are more than a few of functions overloaded like that. Do I have to do the same thing to every function, or is there a better alternative?
Last edited on
Without seeing the actual functions it is hard to advise as to the correct approach.

What is the difference between the two functions (the double, and the "integer" version)?

Have you considered a template class?


Last edited on
It's supposed to be a container class for storing numbers, floating-point and integer in one. Here's a part of it:
1
2
3
Number& set(const Number&);
Number& set(const int&);
Number& set(const double&);

There is an integer and a floating-point overload because I want it to accept both of them. It should be able to convert between the two. Before changing the data types storing the values are int and double. Now I changed it to long and double.
Without seeing the actual functions it is hard to advise as to the correct approach.


Have you considered a template class?
Well here's the .h file if you want to see it (before changing to long):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#pragma once
#ifndef _NUMBER_H_
#define _NUMBER_H_
#include <cmath>
#include <iostream>
using namespace std;
class Number {
private:
	double dVal = 0;
	int iVal = 0;
	bool isInteger;
public:
	Number();
	Number(int);
	Number(double);
	Number(const Number&);

	double val() const;
	int intVal() const;
	bool isInt() const;
	Number& checkInt();
	Number& forceInt();
	Number& forceDouble();
	Number& print();
	const Number& print() const;
	Number& print(ostream&);
	const Number& print(ostream&) const;
	Number& printl();
	const Number& printl() const;
	Number& printl(ostream&);
	const Number& printl(ostream&) const;
	bool equals(const Number&) const;
	bool equals(const int&) const;
	bool equals(const double&) const;
	Number& set(const Number&);
	Number& set(const int&);
	Number& set(const double&);
	bool isMoreThan(const Number&) const;
	bool isMoreThan(const int&) const;
	bool isMoreThan(const double&) const;
	bool isLessThan(const Number&) const;
	bool isLessThan(const int&) const;
	bool isLessThan(const double&) const;
	bool isMoreThanOrEquals(const Number&) const;
	bool isMoreThanOrEquals(const int&) const;
	bool isMoreThanOrEquals(const double&) const;
	bool isLessThanOrEquals(const Number&) const;
	bool isLessThanOrEquals(const int&) const;
	bool isLessThanOrEquals(const double&) const;
	double plus(const Number&) const;
	double plus(const int&) const;
	double plus(const double&) const;
	double minus(const Number&) const;
	double minus(const int&) const;
	double minus(const double&) const;
	double times(const Number&) const;
	double times(const int&) const;
	double times(const double&) const;
	double divideBy(const Number&) const;
	double divideBy(const int&) const;
	double divideBy(const double&) const;
	double mod(const Number&) const;
	double mod(const int&) const;
	double mod(const double&) const;
	Number& plusEquals(const Number&);
	Number& plusEquals(const int&);
	Number& plusEquals(const double&);
	Number& minusEquals(const Number&);
	Number& minusEquals(const int&);
	Number& minusEquals(const double&);
	Number& timesEquals(const Number&);
	Number& timesEquals(const int&);
	Number& timesEquals(const double&);
	Number& divideEquals(const Number&);
	Number& divideEquals(const int&);
	Number& divideEquals(const double&);
	Number& modEquals(const Number&);
	Number& modEquals(const int&);
	Number& modEquals(const double&);

	bool operator==(const Number&) const;
	bool operator==(const int&) const;
	bool operator==(const double&) const;
	friend bool operator==(const int&, const Number&);
	friend bool operator==(const double&, const Number&);
	Number& operator=(const Number&);
	Number& operator=(const int&);
	Number& operator=(const double&);
	bool operator>(const Number&) const;
	bool operator>(const int&) const;
	bool operator>(const double&) const;
	friend bool operator>(const int&, const Number&);
	friend bool operator>(const double&, const Number&);
	bool operator<(const Number&) const;
	bool operator<(const int&) const;
	bool operator<(const double&) const;
	friend bool operator<(const int&, const Number&);
	friend bool operator<(const double&, const Number&);
	bool operator>=(const Number&) const;
	bool operator>=(const int&) const;
	bool operator>=(const double&) const;
	friend bool operator>=(const int&, const Number&);
	friend bool operator>=(const double&, const Number&);
	bool operator<=(const Number&) const;
	bool operator<=(const int&) const;
	bool operator<=(const double&) const;
	friend bool operator<=(const int&, const Number&);
	friend bool operator<=(const double&, const Number&);
	double operator+(const Number&) const;
	double operator+(const int&) const;
	double operator+(const double&) const;
	friend double operator+(const int&, const Number&);
	friend double operator+(const double&, const Number&);
	double operator-(const Number&) const;
	double operator-(const int&) const;
	double operator-(const double&) const;
	friend double operator-(const int&, const Number&);
	friend double operator-(const double&, const Number&);
	double operator*(const Number&) const;
	double operator*(const int&) const;
	double operator*(const double&) const;
	friend double operator*(const int&, const Number&);
	friend double operator*(const double&, const Number&);
	double operator/(const Number&) const;
	double operator/(const int&) const;
	double operator/(const double&) const;
	friend double operator/(const int&, const Number&);
	friend double operator/(const double&, const Number&);
	double operator%(const Number&) const;
	double operator%(const int&) const;
	double operator%(const double&) const;
	friend double operator%(const int&, const Number&);
	friend double operator%(const double&, const Number&);
	Number& operator+=(const Number&);
	Number& operator+=(const int&);
	Number& operator+=(const double&);
	Number& operator-=(const Number&);
	Number& operator-=(const int&);
	Number& operator-=(const double&);
	Number& operator*=(const Number&);
	Number& operator*=(const int&);
	Number& operator*=(const double&);
	Number& operator/=(const Number&);
	Number& operator/=(const int&);
	Number& operator/=(const double&);
	Number& operator%=(const Number&);
	Number& operator%=(const int&);
	Number& operator%=(const double&);
	Number& operator++();
	Number& operator--();
	Number operator++(int);
	Number operator--(int);
	friend ostream& operator<<(ostream&, const Number&);
	friend istream& operator>>(istream&, Number&);
	operator int() const;
	operator double() const;
	operator bool() const;
};
#endif 


I've tried template classes, but finally gave up because (at least I think) they are not practical in this case, and the fact that I cannot separate the function definitions from the declarations into .h and .cpp files anymore if I use templates.
Oh and here's the .cpp file: (part 1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#include "Number.h"

/* Constructors */
Number::Number() {
	isInteger = true;
	iVal = 0;
	dVal = 0.0;
}
Number::Number(int num) {
	isInteger = true;
	iVal = num;
	dVal = 0.0;
}
Number::Number(double num) {
	if (abs(num - std::round(num)) <= 1e-7) {
		isInteger = true;
		iVal = static_cast<int>(std::round(num));
		dVal = 0.0;
	}
	else {
		isInteger = false;
		dVal = num;
		iVal = 0;
	}
}
Number::Number(const Number& otherNum) {
	isInteger = otherNum.isInteger;
	iVal = otherNum.iVal;
	dVal = otherNum.dVal;
}


/* Member Functions */
/* Value checking functions */
double Number::val() const {
	return isInteger ? static_cast<double>(iVal) : dVal;
}
int Number::intVal() const {
	return isInteger ? iVal : static_cast<int>(std::round(dVal));
}
bool Number::isInt() const {
	return isInteger;
}
/* Integer/floating-point conversion functions */
Number& Number::checkInt() {
	if (isInteger)
		return *this;
	if (abs(dVal - std::round(dVal)) <= 1e-7) {
		isInteger = true;
		iVal = static_cast<int>(std::round(dVal));
		dVal = 0.0;
		return *this;
	}
	else {
		return *this;
	}
}
Number& Number::forceInt() {
	if (isInteger)
		return *this;
	isInteger = true;
	iVal = static_cast<int>(std::round(dVal));
	dVal = 0.0;
	return *this;
}
Number& Number::forceDouble() {
	isInteger = false;
	dVal = static_cast<double>(iVal);
	iVal = 0;
	return *this;
}
/* print() */
Number& Number::print() {
	cout << *this;
	return *this;
}
const Number& Number::print() const {
	cout << *this;
	return *this;
}
Number& Number::print(ostream& out) {
	out << *this;
	return *this;
}
const Number& Number::print(ostream& out) const {
	out << *this;
	return *this;
}
/* printl() */
Number& Number::printl() {
	cout << *this << endl;
	return *this;
}
const Number& Number::printl() const {
	cout << *this << endl;
	return *this;
}
Number& Number::printl(ostream& out) {
	out << *this << endl;
	return *this;
}
const Number& Number::printl(ostream& out) const {
	out << *this << endl;
	return *this;
}
/* equals() */
bool Number::equals(const Number& num) const {
	if (isInteger != num.isInteger)
		return false;
	if (isInteger) {
		return iVal == num.iVal;
	}
	else {
		return abs(dVal - num.dVal) < 1e-7;
	}
}
bool Number::equals(const int& num) const {
	return this->equals(Number(num));
}
bool Number::equals(const double& num) const {
	return this->equals(Number(num));
}
/* set() */
Number& Number::set(const Number& num) {
	isInteger = num.isInteger;
	iVal = num.iVal;
	dVal = num.dVal;
	return *this;
}
Number& Number::set(const int& num) {
	this->set(Number(num));
	return *this;
}
Number& Number::set(const double& num) {
	this->set(Number(num));
	return *this;
}
/* isMoreThan() */
bool Number::isMoreThan(const Number& num) const {
	return (isInteger ? iVal : dVal) > (num.isInteger ? num.iVal : num.dVal);
}
bool Number::isMoreThan(const int& num) const {
	return this->isMoreThan(Number(num));
}
bool Number::isMoreThan(const double& num) const {
	return this->isMoreThan(Number(num));
}
/* isLessThan() */
bool Number::isLessThan(const Number& num) const {
	return (isInteger ? iVal : dVal) < (num.isInteger ? num.iVal : num.dVal);
}
bool Number::isLessThan(const int& num) const {
	return this->isLessThan(Number(num));
}
bool Number::isLessThan(const double& num) const {
	return this->isLessThan(Number(num));
}
/* isMoreThanOrEquals() */
bool Number::isMoreThanOrEquals(const Number& num) const {
	return !(this->isLessThan(num));
}
bool Number::isMoreThanOrEquals(const int& num) const {
	return !(this->isLessThan(num));
}
bool Number::isMoreThanOrEquals(const double& num) const {
	return !(this->isLessThan(num));
}
/* isLessThanOrEquals() */
bool Number::isLessThanOrEquals(const Number& num) const {
	return !(this->isMoreThan(num));
}
bool Number::isLessThanOrEquals(const int& num) const {
	return !(this->isMoreThan(num));
}
bool Number::isLessThanOrEquals(const double& num) const {
	return !(this->isMoreThan(num));
}
/* plus() */
double Number::plus(const Number& num) const {
	return (isInteger ? iVal : dVal) + (num.isInteger ? num.iVal : num.dVal);
}
double Number::plus(const int& num) const {
	return this->plus(Number(num));
}
double Number::plus(const double& num) const {
	return this->plus(Number(num));
}
/* minus() */
double Number::minus(const Number& num) const {
	return (isInteger ? iVal : dVal) - (num.isInteger ? num.iVal : num.dVal);
}
double Number::minus(const int& num) const {
	return this->minus(Number(num));
}
double Number::minus(const double& num) const {
	return this->minus(Number(num));
}
/* times() */
double Number::times(const Number& num) const {
	return (isInteger ? iVal : dVal) * (num.isInteger ? num.iVal : num.dVal);
}
double Number::times(const int& num) const {
	return this->times(Number(num));
}
double Number::times(const double& num) const {
	return this->times(Number(num));
}
/* divideBy() */
double Number::divideBy(const Number& num) const {
	if (isInteger && num.isInteger) {
		int result = iVal / num.iVal;
		return result;
	}
	else {
		return (isInteger ? iVal : dVal) / (num.isInteger ? num.iVal : num.dVal);
	}
}
double Number::divideBy(const int& num) const {
	return this->divideBy(Number(num).forceInt());
}
double Number::divideBy(const double& num) const {
	return this->divideBy(Number(num).forceDouble());
}
/* mod() */
double Number::mod(const Number& num) const {
	if (isInteger && num.isInteger) {
		return iVal % num.iVal;
	}
	return fmod(isInteger ? static_cast<double>(iVal) : dVal, num.isInteger ? static_cast<double>(num.iVal) : num.dVal);
}
double Number::mod(const int& num) const {
	return this->mod(Number(num));
}
double Number::mod(const double& num) const {
	return this->mod(Number(num));
}
/* plusEquals() */
Number& Number::plusEquals(const Number& num) {
	*(this) = this->plus(num);
	return *this;
}
Number& Number::plusEquals(const int& num) {
	*(this) = this->plus(num);
	return *this;
}
Number& Number::plusEquals(const double& num) {
	*(this) = this->plus(num);
	return *this;
}
/* minusEquals() */
Number& Number::minusEquals(const Number& num) {
	*(this) = this->minus(num);
	return *this;
}
Number& Number::minusEquals(const int& num) {
	*(this) = this->minus(num);
	return *this;
}
Number& Number::minusEquals(const double& num) {
	*(this) = this->minus(num);
	return *this;
}
/* timesEquals() */
Number& Number::timesEquals(const Number& num) {
	*(this) = this->times(num);
	return *this;
}
Number& Number::timesEquals(const int& num) {
	*(this) = this->times(num);
	return *this;
}
Number& Number::timesEquals(const double& num) {
	*(this) = this->times(num);
	return *this;
}
/* divideEquals() */
Number& Number::divideEquals(const Number& num) {
	*(this) = this->divideBy(num);
	return *this;
}
Number& Number::divideEquals(const int& num) {
	*(this) = this->divideBy(num);
	return *this;
}
Number& Number::divideEquals(const double& num) {
	*(this) = this->divideBy(num);
	return *this;
}
/* modEquals() */
Number& Number::modEquals(const Number& num) {
	*(this) = this->mod(num);
	return *this;
}
Number& Number::modEquals(const int& num) {
	*(this) = this->mod(num);
	return *this;
}
Number& Number::modEquals(const double& num) {
	*(this) = this->mod(num);
	return *this;
}
part 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/* Operators */
/* == */
bool Number::operator==(const Number& num) const {
	return this->equals(num);
}
bool Number::operator==(const int& num) const {
	return this->equals(num);
}
bool Number::operator==(const double& num) const {
	return this->equals(num);
}
bool operator==(const int& num1, const Number& num2) {
	return Number(num1).equals(num2);
}
bool operator==(const double& num1, const Number& num2) {
	return Number(num1).equals(num2);
}
/* = */
Number& Number::operator=(const Number& num) {
	this->set(num);
	return *this;
}
Number& Number::operator=(const int& num) {
	this->set(num);
	return *this;
}
Number& Number::operator=(const double& num) {
	this->set(num);
	return *this;
}
/* > */
bool Number::operator>(const Number& num) const {
	return this->isMoreThan(num);
}
bool Number::operator>(const int& num) const {
	return this->isMoreThan(num);
}
bool Number::operator>(const double& num) const {
	return this->isMoreThan(num);
}
bool operator>(const int& num1, const Number& num2) {
	return Number(num1).isMoreThan(num2);
}
bool operator>(const double& num1, const Number& num2) {
	return Number(num1).isMoreThan(num2);
}
/* < */
bool Number::operator<(const Number& num) const {
	return this->isLessThan(num);
}
bool Number::operator<(const int& num) const {
	return this->isLessThan(num);
}
bool Number::operator<(const double& num) const {
	return this->isLessThan(num);
}
bool operator<(const int& num1, const Number& num2) {
	return Number(num1).isLessThan(num2);
}
bool operator<(const double& num1, const Number& num2) {
	return Number(num1).isLessThan(num2);
}
/* >= */
bool Number::operator>=(const Number& num) const {
	return this->isMoreThanOrEquals(num);
}
bool Number::operator>=(const int& num) const {
	return this->isMoreThanOrEquals(num);
}
bool Number::operator>=(const double& num) const {
	return this->isMoreThanOrEquals(num);
}
bool operator>=(const int& num1, const Number& num2) {
	return Number(num1).isMoreThanOrEquals(num2);
}
bool operator>=(const double& num1, const Number& num2) {
	return Number(num1).isMoreThanOrEquals(num2);
}
/* <= */
bool Number::operator<=(const Number& num) const {
	return this->isLessThanOrEquals(num);
}
bool Number::operator<=(const int& num) const {
	return this->isLessThanOrEquals(num);
}
bool Number::operator<=(const double& num) const {
	return this->isLessThanOrEquals(num);
}
bool operator<=(const int& num1, const Number& num2) {
	return Number(num1).isLessThanOrEquals(num2);
}
bool operator<=(const double& num1, const Number& num2) {
	return Number(num1).isLessThanOrEquals(num2);
}
/* + */
double Number::operator+(const Number& num) const {
	return this->plus(num);
}
double Number::operator+(const int& num) const {
	return this->plus(num);
}
double Number::operator+(const double& num) const {
	return this->plus(num);
}
double operator+(const int& num1, const Number& num2) {
	return num2.isInteger ? (num1 + num2.iVal) : (num1 + num2.dVal);
}
double operator+(const double& num1, const Number& num2) {
	return num2.isInteger ? (num1 + num2.iVal) : (num1 + num2.dVal);
}
/* - */
double Number::operator-(const Number& num) const {
	return this->minus(num);
}
double Number::operator-(const int& num) const {
	return this->minus(num);
}
double Number::operator-(const double& num) const {
	return this->minus(num);
}
double operator-(const int& num1, const Number& num2) {
	return Number(num1).minus(num2);
}
double operator-(const double& num1, const Number& num2) {
	return Number(num1).minus(num2);
}
/* * */
double Number::operator*(const Number& num) const {
	return this->times(num);
}
double Number::operator*(const int& num) const {
	return this->times(num);
}
double Number::operator*(const double& num) const {
	return this->times(num);
}
double operator*(const int& num1, const Number& num2) {
	return num1 * (num2.isInteger ? num2.iVal : num2.dVal);
}
double operator*(const double& num1, const Number& num2) {
	return num1 * (num2.isInteger ? num2.iVal : num2.dVal);
}
/* / */
double Number::operator/(const Number& num) const {
	return this->divideBy(num);
}
double Number::operator/(const int& num) const {
	return this->divideBy(num);
}
double Number::operator/(const double& num) const {
	return this->divideBy(num);
}
double operator/(const int& num1, const Number& num2) {
	return Number(num1).divideBy(num2);
}
double operator/(const double& num1, const Number& num2) {
	return Number(num1).forceDouble().divideBy(num2);
}
/* % */
double Number::operator%(const Number& num) const {
	return this->mod(num);
}
double Number::operator%(const int& num) const {
	return this->mod(num);
}
double Number::operator%(const double& num) const {
	return this->mod(num);
}
double operator%(const int& num1, const Number& num2) {
	return Number(num1).mod(num2);
}
double operator%(const double& num1, const Number& num2) {
	return Number(num1).mod(num2);
}
/* += */
Number& Number::operator+=(const Number& num) {
	return this->plusEquals(num);
}
Number& Number::operator+=(const int& num) {
	return this->plusEquals(num);
}
Number& Number::operator+=(const double& num) {
	return this->plusEquals(num);
}
/* -= */
Number& Number::operator-=(const Number& num) {
	return this->minusEquals(num);
}
Number& Number::operator-=(const int& num) {
	return this->minusEquals(num);
}
Number& Number::operator-=(const double& num) {
	return this->minusEquals(num);
}
/* *= */
Number& Number::operator*=(const Number& num) {
	return this->timesEquals(num);
}
Number& Number::operator*=(const int& num) {
	return this->timesEquals(num);
}
Number& Number::operator*=(const double& num) {
	return this->timesEquals(num);
}
/* /= */
Number& Number::operator/=(const Number& num) {
	return this->divideEquals(num);
}
Number& Number::operator/=(const int& num) {
	return this->divideEquals(num);
}
Number& Number::operator/=(const double& num) {
	return this->divideEquals(num);
}
/* %= */
Number& Number::operator%=(const Number& num) {
	return this->modEquals(num);
}
Number& Number::operator%=(const int& num) {
	return this->modEquals(num);
}
Number& Number::operator%=(const double& num) {
	return this->modEquals(num);
}
/* ++, -- */
Number& Number::operator++() {
	return this->plusEquals(1);
}
Number& Number::operator--() {
	return this->minusEquals(1);
}
Number Number::operator++(int) {
	Number temp(*this);
	this->plusEquals(1);
	return temp;
}
Number Number::operator--(int) {
	Number temp(*this);
	this->minusEquals(1);
	return temp;
}
/* I/O operators */
ostream& operator<<(ostream& out, const Number& num) {
	out << (num.isInteger ? num.iVal : num.dVal);
	return out;
}
istream& operator>>(istream& in, Number& num) {
	double val;
	in >> val;
	num = val;
	return in;
}
/* Type conversion operators */
Number::operator int() const {
	if (isInteger)
		return iVal;
	return static_cast<int>(std::round(dVal));
}
Number::operator double() const {
	if (isInteger)
		return static_cast<double>(iVal);
	return dVal;
}
Number::operator bool() const {
	if (isInteger)
		return iVal != 0;
	return abs(dVal - 0.0) < 1e-7;
}
I've tried template classes, but finally gave up because (at least I think) they are not practical in this case,

Why do you think they are not practical in this case? At a quick glance this class looks like an excellent candidate for using templates.

and the fact that I cannot separate the function definitions from the declarations into .h and .cpp files anymore if I use templates.

And why do you think this is a problem?

If you were to use templates your code would probably decrease by a factor of about three, so that should make implementing your class easier in the long run.

I used templates in another way... When I tried templates, I made the arguments what data type should the number be stored in if it is an integer and what it should be if it is a floating-point. Do you mean to use templates like this:
1
2
template <typename T>
Number& set(T num);

?

I'll try that. Seems like a great idea. Thanks!
Hi,

It seems you have an operator that calls a function (with the same name) which calls another function which calls the constructor. For example operator%= calls modEquals(num), which calls this->mod(num), which calls this->mod(Number(num)) ( including the constructor call), which finally returns iVal % num.iVal;

I am guessing if you use templates your code will reduce by a factor of 12.

But really what you have done is to overload all the language operators in order to partially achieve something the language does anyway. What is the advantage of this Number class that stores either a double or an int? The language already does the right thing with num1 operator num2; using a predefined set of rules, never mind what the type or operator is.
@TheIdeasMan By creating this Number class I hope to achieve a generic Number class that combines both integers and floating-points like those in JavaScript. This way, in some places where you are not sure if the user would enter an integer or floating-point, you can use a Number, which would completely eliminate floating-point precision errors if the user entered an integer.
This way, in some places where you are not sure if the user would enter an integer or floating-point, .....


There are things called unions which can hold one of a selected type at a time.

http://en.cppreference.com/w/cpp/language/union

But as I said there is already a well defined set rules to cope with mixing of integral and floating point types, so using a union probably isn't worth it either. There is also well defined methods of dealing with FP values properly. And we have templates, which one would use for functions and classes, not for the numbers themselves.


..... which would completely eliminate floating-point precision errors if the user entered an integer.


I doubt that you will achieve that with the built-in types, static-casting an int is no different than assigning an int to a double. There will always be numbers that don't convert exactly (even if say one uses a FP with 100 sf ), that is the nature of the current floating point methodology of binary fractions. There are exact decimal types, gnu has a decimal class (#include /decimal/decimal.h if you have it)

There is also boost::any http://www.boost.org/doc/libs/1_61_0/doc/html/any.html

I tried to use templates on the constructors, like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Number();
template <typename T>
Number(const T&);
template <typename T>
Number(const T&, const double&);
/* ... */
Number::Number() {
	isInteger = true;
	iVal = 0;
	dVal = 0.0;
}
template <typename T>
Number::Number(const T& num) {
	isInteger = true;
	iVal = num;
	dVal = 0.0;
}
template <typename T>
Number::Number(const T& num, const double& minFloatAmount) : minFloatingPointAmount(minFloatAmount) {
	isInteger = true;
	iVal = num;
	dVal = 0.0;
}
template <>
Number::Number<double>(const double& num) {
	if (abs(num - std::round(num)) <= minFloatingPointAmount) {
		isInteger = true;
		iVal = static_cast<int>(std::round(num));
		dVal = 0.0;
	}
	else {
		isInteger = false;
		dVal = num;
		iVal = 0;
	}
}
template <>
Number::Number<double>(const double& num, const double& minFloatAmount) : minFloatingPointAmount(minFloatAmount) {
	if (abs(num - std::round(num)) <= minFloatingPointAmount) {
		isInteger = true;
		iVal = static_cast<int>(std::round(num));
		dVal = 0.0;
	}
	else {
		isInteger = false;
		dVal = num;
		iVal = 0;
	}
}
template <>
Number::Number<Number>(const Number& otherNum) : minFloatingPointAmount(otherNum.minFloatingPointAmount) {
	isInteger = otherNum.isInteger;
	iVal = otherNum.iVal;
	dVal = otherNum.dVal;
}

(The function declarations and definitions are in the same file now)

But I got two errors (actually, a whole bunch of errors, but I figured all of them were caused by the two) saying "Error C2988 unrecognizable template declaration/definition" and when I double click it it points to Number::Number<double>(const double& num) { and Number::Number<Number>(const Number& otherNum) : minFloatingPointAmount(otherNum.minFloatingPointAmount) {, but not Number::Number<double>(const double& num, const double& minFloatAmount) : minFloatingPointAmount(minFloatAmount) {. And, at the end of the file IntelliSense tells me that "Error: PCH warning: header stop needs to be at global scope. An IntelliSense PCH file was not generated."
What am I doing wrong here?


P.S. If you are wondering what minFloatingPointAmount is, I updated the code and here's a part of the new .h file:
1
2
3
4
5
6
class Number {
protected:
	double dVal = 0.0;
	long iVal = 0;
	bool isInteger = true;
	const double minFloatingPointAmount = 1e-7;
const double minFloatingPointAmount = 1e-7;

Sorry dude but that is going to render your doubles quite ineffective: they may as well be floats ! Are you aware of how many significant figures doubles have compared to float?

There is also boost::variant

http://www.boost.org/doc/libs/1_61_0/doc/html/variant.html

This is also handy as a tutorial:

http://theboostcpplibraries.com/
Well, thanks. From what you've said I figured that the class I'm writing is quite useless, and now I've stopped working on it anyway. Thanks for all the advice though.
Last edited on
Ok, no worries :+)
Topic archived. No new replies allowed.