I have seen numerous other questions with the same error but those are from people who haven't overloaded the >> operator. I am having this issue with a few other programs I have written all very similar to each other as they are practice questions.
I have also looked into my textbook and compared my program with their example programs and can't see where I'm going wrong.
The full error is (in main.cpp)
line 17: error: no match for 'operator>>' (operand types are 'std::ifstream {aka std::basic_ifstream}' and 'Suitcase()')|
Any and all advice is greatly appreciated.
My Header is
//suitcase.h
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#ifndef SUITCASE_H
#define SUITCASE_H
using namespace std;
class Suitcase
{
public:
Suitcase();
Suitcase(double p,double w,double v,string s,string b);
~Suitcase();
double calc_ratio();
friend bool operator>(const Suitcase s1,const Suitcase s2);
friend ostream& operator<<(ostream & out,const Suitcase& s);
friend istream& operator >>(istream& in,Suitcase& s);
private:
double price,weight,volume;
string brand,shop;
};
#endif // SUITCASE_H
My implementation is
//suitcaseimplement.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include "suitcase.h"
using namespace std;
Suitcase::Suitcase()
{
price=0;
weight=0;
volume=0;
shop="";
brand="";
}
Suitcase::Suitcase(double p,double w,double v,string s,string b)
{
price=p;
weight=w;
volume=v;
shop=s;
brand=b;
}
Suitcase::~Suitcase()
{
}
double Suitcase::calc_ratio()
{
return (volume/weight);
}
bool operator>(Suitcase s1,Suitcase s2)
{
if(s1.calc_ratio()>s2.calc_ratio())
return true;
}
ostream& operator<<(ostream & out,const Suitcase& s)
{
out<<"The suitcase with the highest ratio is the "<<s.brand<<endl;
out<<"It is available at "<<s.shop<<endl;
out<<"It weighs "<<s.weight<<"kgs, has a volume of "<<s.volume<<"and costs R"<<s.price<<endl;
return out;
}
istream& operator >>(istream& in,Suitcase& s)
{
in>>s.price>>s.weight>>s.volume>>s.brand>>s.shop;
return in;
}
and finally my main program is.
//main.cpp
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include "suitcase.h"
using namespace std;
int main()
{
ifstream infile;
infile.open("Suitcase.txt");
if(infile.fail())
exit(1);
Suitcase current_suitcase(), best_suitcase();
infile>>best_suitcase;
while(infile>>current_suitcase)
{
if(current_suitcase>best_suitcase)
{
current_suitcase=best_suitcase;
}
}
infile.close();
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout<<best_suitcase;
return 0;
}
This line
Suitcase current_suitcase(), best_suitcase();
declares two functions that return Suitcase instead of defining two variables. This is called the Most vexing parse rule. Removing the superfluous parentheses solves the problem:
Suitcase current_suitcase, best_suitcase;
Also, don't do using namespace std.
In C++ when you have to initialize object without parameters, you must not put the () because it could be parsed as an object definition with an empty initializer or a function declaration the language standard specifies that the ambiguity is always resolved in favour of the function declaration. so instead of
Suitcase current_suitcase(), best_suitcase();
use
Suitcase current_suitcase, best_suitcase;
Note: empty initializer can be called with curly brackets in this way Suitcase current_suitcase{};
Also, just in case:
note that bool operator>(const Suitcase s1,const Suitcase s2); the const qualifier on the params is applied to an object, and those objects are been created by the copy constructor, so the const qualifier is useless in this case, but instead of taken out the const to the params, change those params to alias of objects, so declare the operator in this way bool operator>(const Suitcase& s1,const Suitcase& s2);
if you want to explicit an empty destructor use this sintax Suitcase::~Suitcase() = default; but take in account that C++ has already a default destructor that will do the same thing of an empty destructor like your
it's not a good trend using using namespace std;: instead just declare the function you want to use of that namespace, like so using std::cout; using std::cin;
Related
So, I have recently approched OOP in c++ through university and I found myself with a few problems.
I gave a shot at overloading the ostream operator << and found myself with some problems to solve.
First was that doing the overloading as ostream& operator<<(ostream& outs, const Test&); carries a problem described as \src\Test.h:15:48: error: 'std::ostream& test::Test::operator<<(std::ostream&, const test::Test&)' must take exactly one argument ostream& operator<<(ostream& outs, const Test&);, so, just like I did with the operator == removed the second argument. But once i Try to build the following code i get the error: \src\main.cpp:9:10: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' cout << t;.
I read this error but can't comprhend it, what should I do and what is the mistake I'm doing?
Test.h
#include <iostream>
#include <cstring>
using namespace std;
#ifndef SRC_TEST_H_BECCIO
#define SRC_TEST_H_BECCIO
namespace test {
class Test {
private:
string mStr;
public:
Test(string str);
string getString(){return this->mStr;};
ostream& operator<<(ostream& outs);
};
} /* namespace test */
#endif /* SRC_TEST_H_BECCIO */
Test.cpp
#include "Test.h"
namespace test {
Test::Test(string str) {
this->mStr=str;
}
ostream& Test::operator<<(ostream& outs){
outs << this->getString()<<endl;
return outs;
}
} /* namespace test */
main.cpp
#include <iostream>
#include "Test.h"
using namespace std;
using namespace test;
int main() {
Test t("let's hope this goes well");
cout << t;
return 0;
}
It looks like the order of the arguments is backwards. See https://learn.microsoft.com/en-us/cpp/standard-library/overloading-the-output-operator-for-your-own-classes.
Try this declaration, and a similar implementation:
friend ostream& operator<<(ostream& os, Test t);
While doing some code practice myself I got some Error
student.h file
#pragma once
class Student {
public:
Student() = default;
Student(int id, const char* name, int score);
Student(const Student& s);
Student(Student&& other);
Student& operator=(Student&& other);
virtual ~Student();
**friend std::ostream & operator<<(std::ostream & os, const Student & rhs);**
void print();
private:
int mId;
char* mName;
int mScore;
size_t mSize;
};
student.cpp file
#include "student.h"
#include <iostream>
#include <string>
... //bunch of constructors, override...
std::ostream & operator<<(std::ostream& os, const Student & rhs)
{
os << rhs.mId << rhs.mName << rhs.mScore ; // Compile Error: Cannot Access Student Member(rhs.mId, rhs.mName...)
return os;
}
The Error i got was i cannot access Student class member despite I declared it friend function in student.h
Strange to me, It compiled successfully if i declare #include<iostream> statement in student.cpp file like this
#include <iostream> //change position <iostream> and "student.h"
#include <string>
#include "student.h"
... //bunch of constructors, override...
std::ostream & operator<<(std::ostream& os, const Student & rhs)
{
os << rhs.mId << rhs.mName << rhs.mScore ; //Compile successfully
return os;
}
So, why #include statement sequences are matters? i thought #include statement just copy-paste to my cpp file.
And it also compiled successfully when i declare #include<iostream> to student.h,
so when i include some #include things the Best-case is declare it to header-file?
Could you give me some advise?
I compiled my program in Visual Studio 2019.
In student.h add an include for iosfwd:
#pragma once
#include <iosfwd>
class Student ...
This will ensure correct resolution of the std::ostream symbol and recognize the ostream operator you defined as the one you declared as a friend.
The iosfwd header contains forward declarations of the symbols in iostream header, and it is defined for exactly this scenario.
In C++ we must declare anything before using it.
So your problem is that you haven't declared std::ostream but you have used it in student.h.
An suitable solution is to #include <iostream> in the beginning of student.h, below #pragma once.
You can also put these before class Stduent:
namespace std
{
class ostream;
}
This is called forward declaration.
I'm trying to overload the >> operator in a class inside a namespace, but as soon as I try to use it with a string stream it doesn't work. Here's a distilled version of my code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
namespace Foo {
class Bar {
public:
string str;
friend istream& operator >>(istream& in, Bar& t);
};
}
inline istream& operator >>(istream& in, Foo::Bar& t) {
in >> t.str;
return in;
}
int main() {
Foo::Bar foo;
stringstream("foo") >> foo;
cout << foo.str << endl;
return 0;
}
and here's the error:
main.cpp:22:22: error: no match for ‘operator>>’ (operand types are ‘std::stringstream {aka std::__cxx11::basic_stringstream<char>}’ and ‘Foo::Bar’)
The thing is these other ways of doing it work:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
namespace Foo {
class Bar {
public:
string str;
friend istream& operator >>(istream& in, Foo::Bar& t) {
in >> t.str;
return in;
}
};
}
int main() {
Foo::Bar foo;
stringstream("foo") >> foo;
cout << foo.str << endl;
return 0;
}
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Bar {
public:
string str;
friend istream& operator >>(istream& in, Bar& t);
};
inline istream& operator >>(istream& in, Bar& t) {
in >> t.str;
return in;
}
int main() {
Bar foo;
stringstream("foo") >> foo;
cout << foo.str << endl;
return 0;
}
The thing is, I have no idea why the first way of doing it should be wrong. I'm using the g++ compiler on linux if that helps. Could someone help me understand what's going on?
Thanks to hints from Sam Varshavchik (in the comments above), I've been able to come up with a correct version of the first version:
#include <iostream>
#include <string>
#include <sstream>
namespace Foo {
class Bar {
public:
std::string str;
friend std::istream& operator >>(std::istream& in, Bar& t);
};
std::istream& operator >>(std::istream& in, Bar& t);
}
std::istream& Foo::operator >>(std::istream& in, Foo::Bar& t) {
in >> t.str;
return in;
}
using namespace std;
int main() {
Foo::Bar foo;
stringstream("foo") >> foo;
cout << foo.str << endl;
return 0;
}
The key was making sure that the operator>> function was both declared and defined in the same scope. I still wanted to be able to define the function outside of the namespace braces, so I had to add a declaration inside the namespace so the compiler would know that there's supposed to be that function in the namespace. Keeping the function definition separate allowed me to separate my code into three files, main.cpp, foo.hpp, and foo.cpp:
// main.cpp
#include <iostream>
#include <string>
#include <sstream>
#include "foo.hpp"
using namespace std;
int main() {
Foo::Bar foo;
stringstream("foo") >> foo;
cout << foo.str << endl;
return 0;
}
// foo.hpp
#ifndef FOO_HPP
#define FOO_HPP
#include <string>
#include <iostream>
namespace Foo {
class Bar {
public:
std::string str;
friend std::istream& operator >>(std::istream& in, Bar& t);
};
std::istream& operator >>(std::istream& in, Bar& t);
}
#endif
// foo.cpp
#include "foo.hpp"
std::istream& Foo::operator >>(std::istream& in, Foo::Bar& t) {
in >> t.str;
return in;
}
Anyways, thanks so much for the help! And thanks for not hand-feeding me a solution; it's so much better to learn by figuring it out myself, even if I did get some help pointing me in the right direction.
Header file:
#ifndef CART_H
#define CART_H
#include "Tops.h"
#include <iostream>
#include <vector>
using namespace std;
class Cart
{
public:
Cart();
void addTop(Tops& top);
friend ostream& operator<<(ostream& ostr, const Cart& c);
private:
vector<Tops> tops;
};
#endif
Implementation file:
#include "Cart.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
Cart::Cart() { }
void Cart::addTop(Tops &top)
{
tops.push_back(top);
}
ostream& operator<<(ostream &ostr, const Cart &c)
{
ostr << "TOPS IN CART:\n-------------\n";
for (auto const top : c.tops) {ostr << top << endl; } // no match for 'operator<<'
return ostr;
}
Problem: I keep getting a "no match for operator<<" error and I have no idea why, and I also have no idea what it means. When I google this error, what has caused the error in other people's codes does not apply to mine.
In your declaration you have stated that the Cart argument will be const:
friend ostream& operator<<(ostream& ostr, const Cart& cart);
but your definition does not:
ostream& operator<<(ostream &ostr, Cart &c)
They need to match (either both const or both not - both const would be right here) for the friend declaration to be of any use.
I tried to make a header called Paitent_info.h as you can see here :
#ifdef GUARD_Paitent_info
#define GUARD_Paitent_info
#include <iostream>
#include <string>
#include <vector>
struct Paitent_info {
std::string name;
std::vector<double> tem;
};
bool compare(const Paitent_info&, const Paitent_info&);
std::istream& read(std::istream&, Paitent_info&);
std::istream& read_tem(std::istream&, std::vector<double>&);
#endif
and here is Paitent_info.cpp :
#include "Paitent_info.h"
using std::istream; using std::vector;
bool compare(const Paitent_info& x, const Paitent_info& y)
{
return x.name < y.name;
}
istream& read(istream& ip, Paitent_info& p)
{ // do something
return ip;
}
istream& read_tem(istream& in, vector<double>& tem)
{ // do something
return in;
}
I got many error messages from this code :
std::istream and std::vector has not been declared
Paitent_info does not name a type.
request for member ‘name’ in ‘x’ and 'y', which is of non-class type ‘const int’.
istream does not name a type.
I do not know why I got all these error messages, please help me.
You got a typo in the header guard:
#ifdef GUARD_Paitent_info
should be
#ifndef GUARD_Paitent_info
Currently the guard causes the header to be included only if it already has been included. Think about that for a second ;).