problem with my Number<T> class

Hi, i just made my Number<T> class and I'm having problems doing operations with different types of Numbers

For example
1
2
3
4
Number<double> x = 2.4;
Number<int> y = 2;
cout << x * y << endl; // works great
cout << Y * x << endl; // wrong results, truncates 4.8 to 4 


This is why its happening
I'm returning type of the 1st operand and in 2nd case 1st is <int>
Is there a way i could make this work like its supposed to?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class T, class U>
Number<T> operator*(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() * n2.get());
}
template<class T, class U>
Number<T> operator/(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() / n2.get());
}
template<class T, class U>
Number<T> operator+(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() + n2.get());
}
template<class T, class U>
Number<T> operator-(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() - n2.get());
}


Here is all code
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
#include <vector>
#include <iostream>
using namespace std;

template<class T>
class Number{
public:
	Number(T);
	Number() : val(T(0)){}
	Number(const Number& n);
	Number& operator=(const Number&);

	Number operator+(const Number&) const;
	Number operator-(const Number&) const;
	Number operator*(const Number&) const;
	Number operator/(const Number&) const;
	Number operator%(const Number&) const;



	Number operator+(const T&) const;
	Number operator-(const T&) const;
	Number operator*(const T&) const;
	Number operator/(const T&) const;

	operator double() { return val; }
	operator int() { return val; }

	Number& operator++();
	Number& operator--();

	T get() const { return val; }
	void set(T t){ val = t; }
private:
	T val;
};

template<class T>
Number<T>::Number(T t = T(0)) : val(t){}

template<class T>
Number<T>::Number(const Number& n) : val(n.get()){}

template<class T>
Number<T>& Number<T>::operator=(const Number& n){
	val = n.get();
	return *this;
}

template<class T>
Number<T> Number<T>::operator+(const Number<T>& v)const{
	return Number<T>(val + v.get());
}
template<class T>
Number<T> Number<T>::operator-(const Number<T>& v)const{
	return Number<T>(val - v.get());
}
template<class T>
Number<T> Number<T>::operator*(const Number<T>& v)const{
	return Number<T>(val * v.get());
}
template<class T>
Number<T> Number<T>::operator/(const Number<T>& v)const{
	Number<T> t(val / v.get());
	return t;
}
template<class T>
Number<T> Number<T>::operator%(const Number<T>& n)const{
	return Number<T>(val % n.get());
}


template<class T, class U>
Number<T> operator*(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() * n2.get());
}
template<class T, class U>
Number<T> operator/(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() / n2.get());
}
template<class T, class U>
Number<T> operator+(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() + n2.get());
}
template<class T, class U>
Number<T> operator-(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() - n2.get());
}



template<class T>
Number<T> Number<T>::operator+(const T& v)const{
	return Number<T>(val + v);
}
template<class T>
Number<T> Number<T>::operator-(const T& v)const{
	return Number<T>(val - v);
}
template<class T>
Number<T> Number<T>::operator*(const T& v)const{
	return Number<T>(val * v);
}
template<class T>
Number<T> Number<T>::operator/(const T& v)const{
	Number<T> t(val / v);
	return t;
}

template<class T>
Number<T>& Number<T>::operator++(){
	val++;
	return *this;
}
template<class T>
Number<T>& Number<T>::operator--(){
	val--;
	return *this;
}




template<class T>
ostream& operator<<(ostream& os, const Number<T>& n){
	os << n.get();
	return os;
}

template<class T>
istream& operator>>(istream& is, Number<T>& n){
	T x;

	is >> x;
	if (!is){
		is.clear(ios_base::failbit);
		return is;
	}
	n.set(x);
	return is;
}

int main(){

	Number<double> x = 2.49;
	Number<int> y = 2;
	cout << y * x << endl;


}



EDIT : On cpp.sh its not even compiling, but it did on my visual studio 2013

Side question - why is cpp.sh giving me compiler error
39:29: error: redeclaration of 'Number<T>::Number(T)' may not have default arguments [-fpermissive]

But if if write definition Number(T t = T(0)) : val(t){} inside my class and remove
1
2
template<class T>
Number<T>::Number(T t = T(0)) : val(t){}
it suddenly compiles. Whats going on here?
Last edited on
it suddenly compiles. Whats going on here?
Default parameters are only allowed for the declaration and not the definition of a function.

Is there a way i could make this work like its supposed to?
The problem appears because of line 27: an implicite cast to int. Therefore the operator on line 23 is chosen by the compiler.

I'd say remove line 26/27.
Tnx a lot for reply man.
But if i remove line 27 i wont be able to do stuff like this
1
2
3
int x;
Number<int> y = 40;
x = y;


EDIT : just checked out and removed line 27
Still its not working. I think the problem is here
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class T, class U>
Number<T> operator*(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() * n2.get());
}
template<class T, class U>
Number<T> operator/(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() / n2.get());
}
template<class T, class U>
Number<T> operator+(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() + n2.get());
}
template<class T, class U>
Number<T> operator-(const Number<T>& n1, const Number<U>& n2){
	return Number<T>(n1.get() - n2.get());
}


If left operand is Number<int> operator will return Number<int> and it truncates my result
4.8
to
4

On the other hand if left operand is Number<double> the return type will be Number<double> and im getting the right result
4.8


How could i return Number<Int> if both operands are Number<int> and Number<double> if one of them is Number<double>
Last edited on
The problem appears because of line 27: an implicite cast to int. Therefore the operator on line 23 is chosen by the compiler.


You are right but this doesn't make any sence to me
Try using operator T(){ return val; } instead?
Thank you man, this looks cool however with my new code where i removed all the
1
2
3
4
5
6
7
8
9
10
11
12
template<class T>
Number<T> Number<T>::operator+(const T& v)const{
	return Number<T>(val + v);
}
template<class T>
Number<T> Number<T>::operator-(const T& v)const{
	return Number<T>(val - v);
}
template<class T>
Number<T> Number<T>::operator*(const T& v)const{
	return Number<T>(val * v);
}

because with operator T(){ return val; } i feel like i don't need them anymore I started to have 1 linker error
Error	1	error LNK2019: unresolved external symbol "public: class Number<int> & __thiscall Number<int>::operator=(class Number<int> const &)" (??4?$Number@H@@QAEAAV0@ABV0@@Z) referenced in function "void __cdecl std::swap<class Number<int> >(class Number<int> &,class Number<int> &)" (??$swap@V?$Number@H@@@std@@YAXAAV?$Number@H@@0@Z)
Error	2	error LNK1120: 1 unresolved externals	


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
#include <vector>
#include <iostream>
using namespace std;

template<class T>
class Number{
public:
	Number(T);
	Number() : val(T(0)){}
	Number(const Number& n);
	Number& operator=(const Number&);

	operator T() const { return val; }

	Number& operator++();
	Number& operator--();

	T get() const { return val; }
	void set(T t){ val = t; }
private:
	T val;
};

template<class T>
Number<T>::Number(T t) : val(t){}

template<class T>
Number<T>::Number(const Number& n) : val(n.get()){}


template<class T>
Number<T>& Number<T>::operator++() {
	val++;
	return *this;
}
template<class T>
Number<T>& Number<T>::operator--(){
	val--;
	return *this;
}
template<class T>
ostream& operator<<(ostream& os, const Number<T>& n){
	os << n.get();
	return os;
}
template<class T>
istream& operator>>(istream& is, Number<T>& n){
	T x;

	is >> x;
	if (!is){
		is.clear(ios_base::failbit);
		return is;
	}
	n.set(x);
	return is;
}

int main(){

	Number<double> y2{2.5};          // works great
	cout << "y2 = " << y2 << endl;   
	const Number<double> x = 2.49;   // all good
	const Number<int> y = 2          // very good
	//y++;
	Number<double> x2 = x*y;	 // excellent
	cout << x2 << endl;		 // bellisimo

	vector<Number<int>> vec{ 2};	 // linker error =[
	system("pause");
}


Whats going on now? As i see it element 0 in vector should be initialized to 2 but instead I'm getting error
Even vector<Number<int>> vec{ Number < int > {3} }; gives error
Last edited on
The function on line 11 is never defined in your code. Either define it yourself, or default it so the compiler defines it for you:

Number& operator=(const Number&) = default;
Thank you very much man, this topic can be safely closed now :)
Topics can't be closed. Marking it as solved is sufficient ;)
Topic archived. No new replies allowed.