learning C++ right now and ran into a bit of a problem. While trying to complete an example and make sure it works ran into the error:
error: no match for 'operator>>' (operand types are 'std::istream' and 'const int')
conversion of argument 1 would be ill-formed
Here is my code,
#include <iostream>
#include <sstream>
#include <cstdlib>
using namespace std;
class Distance {
private:
int feet;
int inches;
public:
Distance() {
feet = 0;
inches = 0;
}
Distance(int f, int i) {
feet = f;
inches = i;
}
friend ostream &operator<<( ostream &output, const Distance &D ) {
output << D.feet << "\'" << D.inches << "\"" << endl;
return output;
}
friend istream &operator>>( istream &input, const Distance &D ) {
input >> D.feet >> D.inches;
return input;
}
};
int main() {
Distance D1(11,10), D2(5,11), D3;
cin >> D3;
cout << "First Distance : " << D1 << endl;
cout << "Second Distance : " << D2 << endl;
cout << "Third Distance : " << D3 << endl;
return 0;
}
Trying to overload the istream and ostream operators, but running into problems with the istream operator >>.
First thought to convert the variable D.feet and D.inches to char* but that doesn't seem right considering that I have to feed an int into the variables. Not sure what is wrong with my code, can anyone help?
Remove const in >> operator overload.
Your Distance is const'd.
[SOLVED]
Figured out the problem in this was that the 'const' in
ostream &operator>>( istream &input , const Distance &D )
Can't explain the actual processes and why this is a conflict, but perhaps somebody else could please explain? I'd really like to know it in depth.
Thanks!
Related
So I tried to make program according to Title of this question, and my code only couts the first one.
Here's the code
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class Distance {
int feet;
int inches;
string display();
public:
Distance();
Distance(int, int);
Distance operator+(Distance);
friend string operator<<(ostream&, Distance);
friend string operator<<(string, Distance);
friend string operator<<(Distance, Distance);
};
Distance::Distance() {
feet = 0;
inches = 0;
}
Distance::Distance(int feet, int inches) {
this->feet = feet;
this->inches = inches;
}
string Distance::display() {
stringstream str;
str << feet << '\'' << inches << '\n';
return str.str();
}
string operator<<(ostream& os, Distance distance) {
string out = distance.display();
os << out;
return out;
}
string operator<<(string str, Distance distance) {
return (str + distance.display());
}
string operator<<(Distance distance1, Distance distance2) {
return distance1.display() + distance2.display();
}
int main() {
Distance distance(5, 8);
Distance distance2(5, 9);
cout << distance << distance2;
}
I've tried multiple ways and one that worked is if I put brackets in that cout line like this cout << (distance << distance2); then it works fine!
But I want it to work without brackets like you know how we do it with strings cout << "abc" << "def"; Now I don't know if it's even possible with objects.
Here are some screenshots of output
without brackets ↴ cout << distance << distance2;
with brackets ↴ cout << (distance << distance2);
If it's not possible to get same output as with brackets without using brackets then can someone please let me know how it works with strings ? like we don't put brackets with strings yet still it displays whole.
cout << "abc" << "def";
output: "abcdef"
The normal thing to do is to simply have one overload
//This requires a friend declaration inside the class first.
std::ostream& operator<<(std::ostream& os, const Distance &distance) {
return os << distance.feet << '\'' << distance.inches << '\n';
}
This lets you chain as expected:
std::cout << 3 << myDistance << myDistance << "hi!"
To support chaining, operator<<(ostream&, Distance) needs to return the ostream& it is given, not string. Also, the Distance should be passed by const reference:
ostream& operator<<(ostream& os, const Distance &distance) {
os << distance.display();
return os;
}
operator<<(string, Distance) and operator<<(Distance, Distance) simply make no sense to have, and so they should be removed completely.
You have implemented operator<<(ostream&, Distance) incorrectly.
Since you have it returning a string, the line:
cout << distance << distance2;
Evaluates cout << distance first, and then resolves to...
{temporary std::string} << distance2;
... which of course doesn't print anything more.
Have the function return a reference to the left parameter instead.
ostream& operator<<(ostream& os, Distance distance) {
string out = distance.display();
os << out;
return os;
}
#include <iostream>
using namespace std;
class A {
public:
int first;
int last;
A(int x = 0, int y = 0):first(x), last(y){}
A(A&a) { cout << "c ctor \n"; }
};
ostream& operator<<(ostream& os, A b) {
os << "first:" << b.first << " last:" << b.last << endl;
return os;
}
istream& operator>>(istream& is, A a) {
is >> a.first >> a.last;
return is;
}
int main()
{
A i;
cout << "enter first and last: \n";
cin >> i;
cout << i;
system("pause");
return 0;
}
A a is a new A object in the >> overload, and if we enter 6 4 into it, the program will remember it in the << overload function, and print what we entered into it. Can someone explain why? Thanks.
This is a wrong statement relative to your presented code because the operator >> deals with a copy of the original object used as an argument of the operator.
The operator should be declared like
istream& operator>>(istream& is, A &a) {
is >> a.first >> a.last;
return is;
}
And moreover the copy constructor does not copies data members.
So the program has undefined behavior. For example running it using clang HEAD 11.0.0 you can get the following result
prog.cc:8:9: warning: unused parameter 'a' [-Wunused-parameter]
A(A&a) { cout << "c ctor \n"; }
^
1 warning generated.
enter first and last:
c ctor
c ctor
first:4202496 last:0
That is the program outputs the variables first and last with indeterminate values because the data members of the created object b in the operator << were not initialized.
#include <iostream>
#include <fstream>
using namespace std;
class InsurancePolicy
{
friend fstream& operator<<(fstream&, InsurancePolicy);
friend istream& operator>>(istream&, InsurancePolicy&);
private:
int policyNum;
string lastName;
int value;
int premium;
};
fstream& operator<<(fstream& out, const InsurancePolicy pol)
{
out << pol.policyNum << " " << pol.lastName << " " << pol.value << " " << pol.premium << endl;
return out;
}
istream& operator>>(istream& in, InsurancePolicy& pol)
{
in >> pol.policyNum >> pol.lastName >> pol.value >> pol.premium;
return in;
}
int main() {
ofstream outFile;
outFile.open("Policy.txt");
InsurancePolicy aPolicy[10];
for (int count = 0; count < 10; ++count)
{
printf("Enter the policy number, the holder's last name, the value, and the premium.");
cin >> aPolicy[count];
outFile << aPolicy[count] << endl;
}
return 0;
}
This program will not compile because of the following errors:
Severity
Code
Description
Project
File
Line
Suppression State
Error
C2679
binary '>>': no operator found which takes a right-hand operand of type 'std::string' (or there is no acceptable conversion)
Project6
c:\users\preston freeman\source\repos\jave.cpp
21
Error
C2679
binary '<<': no operator found which takes a right-hand operand of type 'const std::string' (or there is no acceptable conversion)
Project6
c:\users\preston freeman\source\repos\jave.cpp
16
Error
C2679
binary '<<': no operator found which takes a right-hand operand of type 'InsurancePolicy' (or there is no acceptable conversion)
Project6
c:\users\preston freeman\source\repos\jave.cpp
32
How do I fix these errors?
Thank you for your time.
You are using
ofstream outFile;
in main.
But your operator overloading is
friend fstream& operator<<(fstream&, InsurancePolicy);
Note that ofstream is not derived from fstream, that's why overloading operator << for fstream won't make it work for ofstream
You can simply change fstream to ofstream
ofstream& operator<<(ofstream& out, const InsurancePolicy pol)
{
out << pol.policyNum << " " << pol.lastName << " " << pol.value << " " << pol.premium << endl;
return out;
}
And better to pass in InsurancePolicy by const& since ofstream won't change it, and copy a user defined object can be expensive
ofstream& operator<<(ofstream& out, const InsurancePolicy& pol)
You may also need to #include <string>
Demo:
https://ideone.com/rJiw21
I'm working on boost::asio::streambuf and found out that I can send/get a struct using it, but when I send a struct I just can't get it as I have sent it. The documentation says that one should use commit() and consume(), but where should I use them here?
struct person
{
int m_id;
std::string m_message;
};
std::istream& operator>>(std::istream& in, struct person& p)
{
return in >> p.m_id >> p.m_message;
}
std::ostream& operator<<(std::ostream& out, struct person& p)
{
return out << p.m_id << " " << p.m_message;
}
int main()
{
boost::asio::streambuf buf;
std::ostream out(&buf);
person p;
p.m_id = 1;
p.m_message = "Hello World!";
out << p;
std::istream in(&buf);
person p1;
in >> p1;
cout << "ID: " << p1.m_id << endl;
cout << "Message: " << p1.m_message << endl;
return 0;
}
The problem is with strings so when I type only "hello" (without world), it works fine, but if I add "world!" as shown above it just doesn't see the added "world!", why?
There are a number of issues.
Firstly, make the arguments const& when possible:
std::ostream &operator<<(std::ostream &out, person const &p) {
Secondly, make sure the streams flush to the buffer. I think it's good practice to limit the lifetime of the ostream or istream instances
Thirdly, choose a format that will be robust. Your sample already had bigger problems, when you had m_id = 1 and m_message = "123" (can you see it?).
In text formats you need either fixed-length fields or a delimiting protocol. Let's fix it:
std::ostream &operator<<(std::ostream &out, person const &p) {
return out << p.m_id << ";" << p.m_message.length() << ";" << p.m_message;
}
Now when reading it back you will see how much more precise you need to be:
std::istream &operator>>(std::istream &in, person &p) {
char separator;
size_t length;
bool ok = in >> p.m_id
&& in >> separator && separator == ';'
&& in >> length
&& in >> separator && separator == ';'
;
if (ok) {
p.m_message.resize(length);
in.read(&p.m_message[0], length);
p.m_message.resize(in.gcount());
}
// ensure the expected number of bytes were read
ok = ok && (p.m_message.length() == length);
if (!ok)
in.setstate(std::ios::failbit);
return in;
}
Yikes. Really? Yes really. At a minimum!
Do error handling
Full Demo
Live On Coliru
#include <boost/asio.hpp>
#include <iostream>
struct person {
int m_id;
std::string m_message;
};
std::ostream &operator<<(std::ostream &out, person const &p) {
return out << p.m_id << ";" << p.m_message.length() << ";" << p.m_message;
}
std::istream &operator>>(std::istream &in, person &p) {
char separator;
size_t length;
bool ok = in >> p.m_id
&& in >> separator && separator == ';'
&& in >> length
&& in >> separator && separator == ';'
;
if (ok) {
p.m_message.resize(length);
in.read(&p.m_message[0], length);
p.m_message.resize(in.gcount());
}
// ensure the expected number of bytes were read
ok = ok && (p.m_message.length() == length);
if (!ok)
in.setstate(std::ios::failbit);
return in;
}
int main() {
boost::asio::streambuf buf;
std::ostream(&buf) << person{ 1, "Hello World!" };
person received;
if (std::istream(&buf) >> received) {
std::cout << "ID: " << received.m_id << std::endl;
std::cout << "Message: " << received.m_message << std::endl;
} else {
std::cout << "Couldn't receive person\n";
}
}
Prints
ID: 1
Message: Hello World!
BONUS
C++14 added std::quoted:
#include <iomanip>
std::ostream &operator<<(std::ostream &out, person const &p) { return out << p.m_id << std::quoted(p.m_message); }
std::istream &operator>>(std::istream &in, person &p) { return in >> p.m_id >> std::quoted(p.m_message); }
Which, in this case, also does the job: Live On Coliru
From http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt (emphasis and ellipsis mine):
2) ... reads characters from is and appends them to str ... until one
of the following conditions becomes true:
...
...
std::isspace(c,is.getloc()) is true for the next character c in is (this whitespace character remains in the input stream). ...
Basicaly what this means is that if you extract a string from an istream using operator >> it stops at white spaces.
If you want to get everything from the stream into your string there are plenty of questions asking that (Like this one or this one).
I don't know why cout << da << '\n' works fine,but std::cout << next_Monday(da) << '\n' went wrong. Why the direct Date object can output, but the return Date can't.
Why overloaded operator << works sometimes but other times doesn't.
here is my code..
#include <iostream>
#include <stdlib.h>
struct Date {
unsigned day_: 5;
unsigned month_ : 4;
int year_: 15;
};
std::ostream& operator<<(std::ostream& out,Date& b)
{
out << b.month_ << '/' << b.day_ << '/' << b.year_;
return out;
}
std::istream& operator>>(std::istream& in,Date& b);
Date next_Monday(Date const &d);
int main()
{
Date da;
std::cin >> da;
std::cout << da << '\n';
std::cout << next_Monday(da) << '\n';
return 0;
}
this is what clang said: (I use g++ to invoke)
excercise19DateManipulate.cpp:114:18: error: invalid operands to binary
expression ('ostream' (aka 'basic_ostream<char>') and 'Date')
std::cout<< next_Monday(da) <<'\n';
~~~~~~~~^ ~~~~~~~~~~~~~~~
Because you can't bind a temporary to a non-const lvalue reference. Change the operator to take a const reference:
std::ostream& operator<<(std::ostream& out, const Date& b)
You never defined the "next_Monday()" function as far as I can see, you only declared it.