'operator <<' is ambiguous

hi,

i get this error: error C2593: 'operator <<' is ambiguous

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
#include <iostream>
#include "Fraction.h"
using namespace std;


std::istream& operator>>(std::istream& is, Fraction& rho);
std::ostream& operator<<(std::ostream& os, const float rho);

int main()
{
	Fraction frac;
	cin >> frac;

	Fraction frac1;
	cin >> frac1;

	cout << "Chose operation between the two fractions: " << endl;
	cout << "1.+, 2.-, 3.*, 4./, 5.==, 6.!=, 7.>=, 8.<=; 9.quit" << endl;
	char num = 0;
	cin >> num;

	float operation = 0;
	switch(num)
	{
	case 1:
		operation = frac + frac1;
		break;
	}

	cout << "Result is: " << operation << endl;





}

std::istream& operator>>(std::istream& is, Fraction& rho)
{
	cout << "Enter numerator: ";
	cin >> rho.numerator;
	cout << "Enter denominator: ";
	cin >> rho.denominator;

	return is;
}
	
std::ostream& operator<<(std::ostream& os, const float rho)
{
	cout << rho;

	return os;
}


suggestions? ty (i think i have to do something with "using")
Last edited on
You have the following constructor which is causing the problem:

1
2
3
4
class Fraction {
   public:
       Fraction( float f );
};


To fix this:

1
2
3
4
class Fraction {
   public:
       explicit Fraction( float f );
};


add the keyword explicit. This may break other code. Specifically, if you are relying on the compiler
to perform implicit conversion of floats to Fractions (via the above constructor), this will no longer
happen, and you need to make it explicit:

1
2
3
4
5
// This would stop compiling:
Fraction f = 0.25;

// This is correct:
Fraction f( 0.25 );

Watch your consts in your argument lists. See lines 7 and 48.
ty duoas for reminding me of my mistake...

jsmith: i dont quite understand what i have to do, ive just added explict before custom constructor, but nothing changes
I didn't realize there was a class working with fraction classes until just today...

Mathematically, a fraction is composed of an integer numerator and an integer denominator. You should not have a constructor of the form
Fraction( float f )
(unless, of course, your professor wants otherwise... but it is still a bad idea).

If you must perform conversions from float to Fraction via assignment and the like, then use an explicit constructor like jsmith indicated... this will prevent the compiler from taking too many liberties when it shouldn't. (Remember, a fraction is not a float.) Converting a float to a fraction is not a particularly simple thing to do. (But it can be done, mind you.)

Hopefully you have a constructor something like:
Fraction( int numerator = 0, int denominator = 1 )
This gives you a default constructor, an int to Fraction constructor, and a proper fraction constructor.


I/O operators
(In C++, that's the extraction and insertion operators.)
The purpose of the operator is to allow you to read or write your data to any stream -- the same one given as argument (in your case, that's is and os -- BTW, a word like "is" is not a good name for a variable; I tend to use unambiguous names like "ins" and "outs" for in-stream and out-stream respectively).

However, your operators not only completely ignore the argument streams, but they invoke other streams to perform their task. Worse than that -- the input operator (the 'extract from stream' operator) performs output. That's bad.

The I/O operators should expect input based upon a specific format. For example, you may say that a fraction, when written, must always have the form:

['-'] digits '/' digits

This makes I/O easy -- in fact, it is the natural way we write fractions. Your program might then run:

Enter a fraction: -2/5
You entered -2/5 which is the same as -0.4.

The extraction (input) operator should read the "-2/5" directly. It should not expose the user to the details of how the class is implemented ("Yoinks! That is a numerator and a denominator in there!")

Doing input is typically a bit more difficult than output. You will need to do some error checking on the "/" character of the input. I recommend you use peek() and setstate(). For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
istream& operator >> ( istream& ins, Fraction& frac )
{
	// stuff to read the numerator goes here
	...

	// read the "/" and complain if it isn't
	int c = ins.peek();
	if (c != '/')
	{
		ins.setstate( ios::failbit );
		return ins;
	}

	// stuff to read the denominator goes here
	...

	// return the current stream for the next input operator
	return ins;
}
Notice how cin and cout are not involved anywhere inside the extraction operator function. The code that uses the extraction operator does stuff like:
1
2
3
	Fraction f;
	cout << "Please enter a fraction: " << flush;
	cin >> f;


Output is considerably easier. Just check to make sure your denominator isn't negative before writing things out. You will have to think about how to turn a fraction like:

3
---
-4

into something that prints like "-3/4". Remember, your insertion (output) operator should not modify the object:
ostream& operator << ( ostream& outs, const Fraction& frac )


Well, lunch is calling, so that's all I'm going to say for now.
You might want to point other confused classmates to this post.

Hope this helps.
first of all this is not a school assignment

ok ive seen that i made a major mistake, because i used a float type in << operators parameter (which does not make sence, since float can be outputed in a normal way)

but as it looks it can be used in this way aswell, since youve tought i meant it like that

so heres the modified (main.cpp) 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
#include <iostream>
#include "Fraction.h"
using namespace std;


std::istream& operator>>(std::istream& is, Fraction& rho);
std::ostream& operator<<(std::ostream& os, Fraction& rho);

int main()
{
	Fraction frac;
	cin >> frac;

	Fraction frac1;
	cin >> frac1;

    /*cout << "Chose operation between the two fractions: " << endl;
	cout << "1.+, 2.-, 3.*, 4./, 5.==, 6.!=, 7.>=, 8.<=; 9.quit" << endl;
	char num = 0;
	cin >> num;

	float operation = 0;
	switch(num)
	{
	case 1:
		operation = frac + frac1;
		cout << "Result is: " << operation << endl;
		break;
	}

	cout << "Result is: " << operation << endl;*/

	float a = frac + frac1;
	cout << a;





}

std::istream& operator>>(std::istream& is, Fraction& rho)
{
	cout << "Enter numerator: ";
	cin >> rho.numerator;
	cout << "Enter denominator: ";
	cin >> rho.denominator;

	return is;
}
	
std::ostream& operator<<(std::ostream& os, Fraction& rho)
{
	//cout << rho.numerator << "/" << rho.denominator;
	cout << (float)rho;

	return os;
}


but now the problem is the following:
- if i use those those lines inside /*...*/, i "always" get 0 as a result, but if i use the two lines
(that are in bold) instead of those, i get the correct result

What seems to be the problem?
you mean

case '1':

the code inside case 1 is never executing, which I believe you knew, because you wouldn't see
the "Result is:" output that it does, but you have the same output after the switch.
yea ive finished the program already and now trying to make, so that user can inpu "2/3", and not numerator and denominator seperate....

but in this particular place, i just used int instead of char - why cant i use char?

and why if i use const in ostream (or ostream), i get:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const float' (or there is no acceptable conversion)
(just wondering)
Last edited on
If the user types (without the quotes): "1 <ENTER>"

...and you read into an int, the int value is 1.
...and you read into a char, the char value is '1' (ASCII 0x31, decimal 49)

You do not need to write operator<< for const float (original post, line 7).
Otherwise, you'll need to post your code along with the exact compile error (and line num).
Duoas: can you please tell me how i should implement peek() and setstate() in my code, so that i could input fractions in a normal way? what i did is just this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::istream& operator>>(std::istream& is, Fraction& rho)
{
	cout << "Enter fraction: ";
	cin >> rho.numerator;

	char c = is.peek();
	if (c != '/')
	{
		is.setstate( ios::failbit );
		return is;
	}

	cin >> rho.denominator;  // i know i shoul use cin only once, if i want to inpust in this way:  
                                                // "2/3"
	return is;
}
Last edited on
You are getting much closer.

You shouldn't use cin at all -- the caller of the function handed you the proper object to use: is (which, BTW, I think is not a good name; use "ins" or "inputstream" or somesuch instead).

Also, you should not be using cout either.

Hope this helps.
ok ithink what u meant is that in the operators definitions (in >> and <<), the specified object ofistream that ive made, is now actually the object, which represents cin and cout member definitions of that class, and that i should use this instead of "cin >>" and "cout <<" (because im obviously overloading that operator) - which i did

- how do i implement this:
"// stuff to read the numerator/denominator goes here" ?
Last edited on
ok, i have done the input part in some other, more easy way and im almost at the end

anyway, now im asking if there is a way of using more then 1 character for input, in a way so that it can be put in a switch statement as a case label? (or ill just have to use if statements?)
with +,/,-,* - which are singel characters theres no problem, but with relational operators - ==, !=, >=, <=, there is!

ty in advance

Last edited on
Unfortunately for strings, switch-case is not viable. You'll have to use if-else.

(Alternatively, but this is more advanced, you could create a map of strings to function pointers, look up the string in the map and call the associated function. This gives you very similar behavior to switch statements at the cost of having to build the map.)
you have to use #include <map> right?

can you demonstrate how i could do this in my case (for: ==,!=,>=,<=), if thats ok with you
Last edited on
Here's one simple example of how to select on a string. (See the very last post on the page.)
http://www.cplusplus.com/forum/general/11460/
can i mix ordinary cin with getline - because if i do, i cant input normally (i think it skips the getline part...):

1
2
3
4
5
	cin >> frac;

	getline(cin, operation);

	cin >> frac1;
No. You must clear the newline (and any other extraneous characters left on the line) after using operator >>.
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
#include <iostream>
#include <limits>
#include <string>
using namespace std;

int main()
  {
  double age, favorite_number;
  string name;

  // User enters his age
  cout << "What is your age? " << flush;
  cin >> age;
  cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

  // User enters his name
  cout << "What is your name? " << flush;
  getline( cin, name );

  // User enters his favorite number
  cout << "What is your favorite number? "  << flush;
  cin >> favorite_number;
  cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

  // User gets thrown off bridge...
  cout << "Aaaaiiiieeeeee!\n";
  return 0;
  }

The user expects the press the Enter key after every input.


Some inputs are more complicated than above. For example, inputting an equation is more complex:

12.9 / (3.47 + 2)

The entire input is one line, but you must parse the individual items on the line (numbers, operators, parentheses, etc.)

Hope this helps.
Last edited on
nothing changes...

1
2
3
4
5
6
7
        cin >> frac;
	cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

	getline(cin, operation);

	cin >> frac1;
	cin.ignore( numeric_limits <streamsize> ::max(), '\n' );



what happens is same as before - if i input 67/56 + 676/65, it wants another two inputs (what youve said)
heres the main.cpp, if youll maybe find something that ive made wrong...

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
#include <iostream>
#include <string>
#include <limits>
#include "Fraction.h"
using namespace std;


std::istream& operator>>(std::istream& is, Fraction& rho);
std::ostream& operator<<(std::ostream& os, Fraction& rho);

void singlechar(char one_s, Fraction& frac_compute, Fraction& frac, Fraction& frac1, bool result_validation);
void doublechar(char* doublecharsymbol[], string operation, Fraction& frac, Fraction& frac1);

int main()
{
	char* doublecharsymbol[4];   
	doublecharsymbol[0] = "==";
	doublecharsymbol[1] = "!=";
	doublecharsymbol[2] = ">=";
	doublecharsymbol[3] = "<=";

	string operation = "";

	char one_s; 

	bool new_operation = false;
	bool num4 = false;
	bool quit = false;
	while( !quit )
	{
	int num = 0;

	if(!num4)
	{
	cout << "What would you like to do?" << endl;
	cout << "1.compute fractions, 2.quit" << endl;
	cin >> num;
	}
	else
		num = 1;

	if(num == 1)
	{

	bool quit5 = false;
	Fraction frac;
	Fraction frac1;

	do
	{
	quit5 = false;
	cout << "Enter two fractions (with symbol \"/\") and choose operation between the two:" << endl;
	cout << "+, -, *, /, ==, !=, >, <, >=, <=" << endl;

	cin >> frac;
	cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

	getline(cin, operation);

	cin >> frac1;
	cin.ignore( numeric_limits <streamsize> ::max(), '\n' );


	if(frac.numerator == 0 || frac.denominator == 0 || frac1.numerator == 0 || frac1.denominator == 0)
	{
		cout << "You did not enter a valid fraction/s - you have used zero value as a numerator or/and denominator in some of them." << endl << endl;
	    quit5 = true;
	}
	}
	while(quit5);

	bool quit2 = false;

	bool case3 = false;
	if(!case3)
	
	bool new_operation = false;

	do
	{	
	if(new_operation)
	getline(cin, operation);

	quit2 = false; 


	Fraction frac_compute;
	bool result_validation = true;

	int length = operation.length();
	if(length == 1)
	{


	one_s = operation[0]; 


	singlechar(one_s, frac_compute, frac, frac1, result_validation);
	}
	else if(length > 1)
	doublechar(doublecharsymbol, operation, frac, frac1);

	result_validation = false;


	cout << "You want to:" << endl;
	cout << "1.compute with specified fractions, 2.enter new fractions, 3.quit" << endl;


	bool quit3 = false;
	do
	{
	int num3 = 0;
	cin >> num3;

	switch(num3)
	{
	case 1:
		quit2 = true;
		quit3 = true;
		new_operation = true;
		break;
	case 2:
		num4 = true;
		quit3 = true;
		break;
	case 3:
		cout << "Quiting..." << endl << endl;
		quit = true;
		case3 = true;
		quit3 = true;
		break;
	default:
		cout << "You did not enter a valid number!" << endl;
		quit3 = true;
	}

	}
	while(!quit3);
		
	}
	
	while(quit2 && !case3);  



	}
   
	else if (num == 2)
	{
		cout << "Quiting..." << endl << endl;
		quit = true;
	}

	else
		cout << "Invalid input! Please type a number for selected option again." << endl << endl;

  }
	
}



std::istream& operator>>(std::istream& ins, Fraction& rho)
{

	bool quit = true;
	do
	{
	
	char devide = '/'; 
	cin >> rho.numerator >> devide >> rho.denominator;

	if(devide != '/')
	{
		cout << "You did not enter a valid fraction - you must write fractions with \"/\" symbol!" << endl;
		quit = false;
	}
	else              
		quit = true; 
	}
	while(!quit);


	return ins;
}
	
std::ostream& operator<<(std::ostream& os, Fraction& rho)
{

	{
	bool quit4 = false;
	while(!quit4)
	{
	int remainder_num = (int)rho.numerator % rem_num;    
	int remainder_den = (int)rho.denominator % rem_num;
	if(remainder_num == 0 && remainder_den == 0)
	{
	rho.numerator /= rem_num;
	rho.denominator /= rem_num;
	}
	else 
	quit4 = true;
	}
	}

	cout << rho.numerator << "/" << rho.denominator << ", " << (float)rho;

	return os;
}


void singlechar(char one_s, Fraction& frac_compute, Fraction& frac, Fraction& frac1, bool result_validation)
{
		switch(one_s)
	{
	case '+':
		frac_compute = frac + frac1;
		break;
	case '-':
		frac_compute = frac - frac1;
		break;
	case '*':
		frac_compute = frac * frac1;
		break;
	case '/':
		frac_compute = frac / frac1;
		break;
	case '>':
		if(frac > frac1)
			cout << "Fraction A is greater then fraction B" << endl << endl;
		else
			cout << "Fraction A is less then fraction B" << endl << endl;
		break;
	case '<':
		if(frac < frac1)
			cout << "Fraction A is less then fraction B" << endl << endl;
		else
			cout << "Fraction A is greater then fraction B" << endl << endl;
		break;
		}

	if (one_s == '+' || one_s == '-' || one_s == '*' || one_s == '/' || result_validation == true )
	cout << "Result is: " << frac_compute << endl << endl;
}

void doublechar(char* doublecharsymbol[], string operation, Fraction& frac, Fraction& frac1)
{


	int cnt;
	for(cnt = 0; cnt < 4; cnt++)
	{
		if(doublecharsymbol[cnt] == operation)
		break;
	}

	switch(cnt)
	{
	case 0:
		if(frac == frac1)
			cout << "Fractions are equal!" << endl << endl;
		else
			cout << "Fractions are`nt equal!" << endl << endl;
		break;
	case 1:
		if(frac != frac1)
			cout << "Fractions are`nt equal!" << endl << endl;
		else
			cout << "Fractions are equal!" << endl << endl;
		break;
	case 2:
		if(frac >= frac1)
			cout << "Fraction A is greater then or equel to fraction B" << endl << endl;
		else
			cout << "Fraction A is less then or equel to fraction B" << endl << endl;
		break;
	case 3:
		if(frac <= frac1)
			cout << "Fraction A is less then or equel to fraction B" << endl << endl;
		else
			cout << "Fraction A is greater then or equel to fraction B" << endl << endl;
		break;
	}


}
Topic archived. No new replies allowed.