I wrote the following test program:
int main(int argc, char** argv)
{
ifstream inFile;
inFile.open("D:\\C++\\Assignments\\in1.txt");
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
Complex a,b,c;
inFile >> a;
inFile >> b;
ofstream out;
out.open("D:\\C++\\Assignments\\out1.txt");
out << a <<endl<< b<<endl; // dumps data to a stream connected to a file
out << c=a <<endl;
out.close();
return 0;
}
I have overloaded = as following:
void Complex::operator=(const Complex &a)//mulptiplication
{
real=a.real;
imag=a.imag;
}
But I am getting errors like: no match for ooperator <<. Can anyone help with the error?
This is your problem:
out << c=a <<endl;
You need to return a Complex&
Try this:
Complex& Complex::operator=(const Complex &a)//mulptiplication
{
real=a.real;
imag=a.imag;
return *this;
}
The reason is that c=a yields a void and there is no operator<< that works for void on the left hand side
Just for clarity, you might rewrite as:
c = a;
out << c << endl;
ortang is also right that there must be an operator<< for the Complex class.
The problem lies in out << a << endl << b << endl, since you did not overload the operator<< for the Complex class i guess.
Take a look at this SO post how to overload the operator<<.
If real and imag are themselves of types with correct assign semantics (for example primitive types like int or double), then it is redundant and error-prone to implement your own operator=. Just use the compiler-generated one.
Even with proper operators
out << c=a <<endl;
which is parsed as
(out << c) = (a <<endl);
the error occurs, due to operator precedence.
Related
I am going through "Programming principles and practice using C++" by Bjarne Stroustrup, and I am trying to complete this exercise:
Define a File_handle class with a constructor that takes a string argument (the file name), opens the file in the constructor, and closes it in the destructor.
I was wondering if it was possible to give the user the possibility to extract the reference/pointer to the stream to operate on it and leave to the class the responsibility to close it when out of scope.
It is probably not good practice, but I got interested in the behavior I get (see the code in main()), it doesn't seem possible to access the stream from outside the class, but it works perfectly inside it.
There is probably something very obvious to a trained eye that I am missing, but since I am still trying to learn, I would like to understand why and how things work a bit deeper with stream classes
Also, I would like to know how a more experienced programmer would approach the problem.
I already got similar problems a couple of times, but I couldn't find satisfying answers after a good bit of google-fu, and reading the C++ reference manual.
class File_handle
{
fstream file;
public:
File_handle(string s)
:file{s}
{
if (!file) error("File not found!");
cerr << "Constructed File_handle" << endl;
}
File_handle(const File_handle&) = delete;
File_handle& operator=(const File_handle&) = delete;
~File_handle()
{
cerr << "Destroyed File_handle" << endl;
file.close();
return;
}
fstream& attach() { return file; };
fstream* attach_p() { return &file; };
void print(ostream& os)
{
while (file) {
char c = file.get();
cout << c;
}
}
};
int main()
{
File_handle stream {"TextFile.txt"};
fstream& f = stream.attach();
cout << f; // invalid operands to binary expression
cout << f.get(); // output => 35
fstream* fp = stream.attach_p();
cout << *fp; // invalid operands to binary expression
cout << fp->get(); // output => 35
stream.print(cout); // works fine, prints the whole file
cout << endl;
}
I am trying to overload
<<
operator. For instance
cout << a << " " << b << " "; // I am not allowed to change this line
is given I have to print it in format
<literal_valueof_a><"\n>
<literal_valueof_b><"\n">
<"\n">
I tried to overload << operator giving string as argument but it is not working. So I guess literal
" "
is not a string. If it is not then what is it. And how to overload it?
Kindly help;
Full code
//Begin Program
// Begin -> Non - Editable
#include <iostream>
#include <string>
using namespace std;
// End -> Non -Editable
//---------------------------------------------------------------------
// Begin -> Editable (I have written )
ostream& operator << (ostream& os, const string& str) {
string s = " ";
if(str == " ") {
os << '\n';
}
else {
for(int i = 0; i < str.length(); ++i)
os << str[i];
}
return os;
}
// End -> Editable
//--------------------------------------------------------------------------
// Begin -> No-Editable
int main() {
int a, b;
double s, t;
string mr, ms;
cin >> a >> b >> s >> t ;
cin >> mr >> ms ;
cout << a << " " << b << " " ;
cout << s << " " << t << " " ;
cout << mr << " " << ms ;
return 0;
}
// End -> Non-Editable
//End Program
Inputs and outputs
Input
30 20 5.6 2.3 hello world
Output
30
20
5.6
2.3
hello
world
" " is a string-literal of length one, and thus has type const char[2]. std::string is not related.
Theoretically, you could thus overload it as:
auto& operator<<(std::ostream& os, const char (&s)[2]) {
return os << (*s == ' ' && !s[1] ? +"\n" : +s);
}
While that trumps all the other overloads, now things get really hairy. The problem is that some_ostream << " " is likely not uncommon, even in templates, and now no longer resolves to calling the standard function. Those templates now have a different definition in the affected translation-units than in non-affected ones, thus violating the one-definition-rule.
What you should do, is not try to apply a global solution to a very local problem:
Preferably, modify your code currently streaming the space-character.
Alternatively, write your own stream-buffer which translates it as you wish, into newline.
Sure this is possible, as I have tested. It should be portable since you are specifying an override of a templated function operator<<() included from <iostream>. The " " string in your code is not a std::string, but rather a C-style string (i.e. a const char *). The following definition works correctly:
ostream& operator << (ostream& os, const char *str) {
if(strcmp(str, " ") == 0) {
os << '\n';
} else {
// Call the standard library implementation
operator<< < std::char_traits<char> > (os, str);
}
return os;
}
Note that the space after std::char_traits<char> is necessary only if you are pre-c++11.
Edit 1
I agree with Deduplicator that this is a potentially dangerous solution as it may cause undesirable consequences elsewhere in the code base. If it is needed only in the current file, you could make it a static function (by putting it within an unnamed namespace). Perhaps if you shared more about the specifics of your problem, we could come up with a cleaner solution for you.
You might want to go with a user defined literal, e.g.
struct NewLine {};
std::ostream& operator << (std::ostream& os, NewLine)
{
return os << "\n";
}
NewLine operator ""_nl(const char*, std::size_t) // "nl" for newline
{
return {};
}
This can be used as follows.
int main(int, char **)
{
std::cout << 42 << ""_nl << "43" << ""_nl;
return 0;
}
Note three things here:
You can pass any string literal followed by the literal identifier, ""_nl does the same thing as " "_nl or "hello, world"_nl. You can change this by adjusting the function returning the NewLine object.
This solution is more of an awkward and confusing hack. The only real use case I can imagine is pertaining the option to easily change the behavior at a later point in time.
When doing something non-standard, it's best to make that obvious and explicit - here, the user defined literal indeed shines, because << ""_nl is more likely to catch readers' attention than << " ".
i'd like to ask something rather difficult for me; I have to make a calendar-type program, but with an overloaded '+=' operator.
So it goes like this:
template<typename T1,typename T2,typename T3> //int,int,int
class T_sort_data{
T1 p1;
T2 p2;
T3 p3;
public:
T_sort_data(){
cout << "\n\t Constructed at [" << this << "]\n";};
/ friend ostream& operator<<(ostream& os,const T_sort_data& obj) // get function
{
os << "\nDay : " << obj.p1 << " \n";
os << "Month : " << obj.p2 << " \n";
os << "Year : " << obj.p3 << " \n";
return os;
}*/
void set_date(){
int dd,mm,yy;
cout << "\n\n\tPlease input the day, the month and the year : \n\n";
cin >> dd >> mm >> yy;
p1 = dd;
p2 = mm;
p3 = yy;
}
// validator here, which works ...
T_sort_data<int,int,int>& operator+=(const T_sort_data<int,int,int>& second)
{
p1+=second.p1;
return *this;
}
friend istream& operator>>(istream& is, T_sort_data& obj) // set function
{
is >> obj.p1;
is >> obj.p2;
is >> obj.p3;
return is;
}
~T_sort_data(){
cout << "\n\t Deconstructed [" << this << "]\n";};
};
int main(){
T_sort_data<int,int,int> * a = new T_sort_data<int,int,int> ;
bool more = true;
string answ;
a->set_date();
//cin >> a; (this doesn't work)
//validator goes here
//a += a; (this, again, doesn't work)
delete a;
return 0;
}
Whenever I make an object using "T_sort_data a;" those operations work fine, but whenever I use "T_sort_data * a = new T_sort_data;"
shit hits the fan.
Can anyone help me with this?
You didn't post exactly what is going wrong so I have to infer that from the code.
The issue that you're running into is that overloaded operators work on instances or references to objects, not on pointers to objects. In the cases where your code doesn't work, you're dealing with pointers to objects. So, in order to use your overloaded operators, you need to dereference the pointer (effectively turning it from a pointer pointing to a value into the value itself) before applying the operator, for example:
cin >> *a;
or
*a += *a;
T_sort_data a is a variable of type T_sort_data.
T_sort_data * a is a variable of type pointer to T_sort_data.
Your overloaded operators expect their operands to be of type T_sort_data, not pointer to T_sort_data. Use the unary * operator to dereference the pointers, so that the operand types are what the operators expect.
This is pretty fundamental. Here's the same thing with int and std::cout: http://codepad.org/N07Xckdy
This question already has answers here:
no match for ‘operator<<’ in ‘std::operator
(6 answers)
Closed 5 years ago.
I am developing gsoap web service where I am retrieving vectors of objects in return of a query. I have two ways to do it: first by simple loop and by iterator. None of them working.
The error is:
error: no match for 'operator<<' in 'std::cout
mPer.MultiplePersons::info.std::vector<_Tp, _Alloc>::at<PersonInfo, std::allocator<PersonInfo> >(((std::vector<PersonInfo>::size_type)i))'
MultiplePersons mPer; // Multiple Person is a class, containing vector<PersonInfo> info
std::vector<PersonInfo>info; // PersonInfo is class having attributes Name, sex, etc.
std::vector<PersonInfo>::iterator it;
cout << "First Name: \t";
cin >> firstname;
if (p.idenGetFirstName(firstname, &mPer) == SOAP_OK) {
// for (int i = 0; i < mPer.info.size(); i++) {
// cout << mPer.info.at(i); //Error
//}
for (it = info.begin(); it != info.end(); ++it) {
cout << *it; // Error
}
} else p.soap_stream_fault(std::cerr);
}
It's obvious that operator overloading operator<< in cout is the problem. I have looked at several problems related to this, but no one helped me out. If someone can provide a concrete example on how to solve it, it would be very appreciated. (Please do not talk in general about it, I am new to C++ and I have spent three days on it searching for solution.)
You need to provide an output stream operator for PersonInfo. Something like this:
struct PersonInfo
{
int age;
std::string name;
};
#include <iostream>
std::ostream& operator<<(std::ostream& o, const PersonInfo& p)
{
return o << p.name << " " << p.age;
}
This operator allows expressions of the type A << B, where A is an std::ostream instance (of which std::cout is one) and B is a PersonInfo instance.
This allows you do do something like this:
#include <iostream>
#include <fstream>
int main()
{
PersonInfo p = ....;
std::cout << p << std::endl; // prints name and age to stdout
// std::ofstream is also an std::ostream,
// so we can write PersonInfos to a file
std::ofstream person_file("persons.txt");
person_file << p << std::endl;
}
which in turn allows you to print the de-referenced iterator.
The result of *it is an L-value of type PersonInfo. The compiler is complaining that there is no operator<< which takes a right-hand side argument of type PersonInfo.
For the code to work, you need to provide such an operator, for example like this:
std::ostream& operator<< (std::ostream &str, const PersonInfo &p)
{
str << "Name: " << p.name << "\nAge: " << p.age << '\n';
return str;
}
The exact implementation of the operator depends on your needs for representing the class in output, of course.
What it's telling you is that there isn't a known wway to cout (console output) the contents of *it.
it is an iterator - think of this like a pointer in a list
the list is info so *it is current item in the info, which is a list of PersonInfo items.
So cout << *it; says output to the console the PersonInfo that it is currently referencing.
But the error message is telling you that the compiler doens't know how PersonInfo should be rendered to the console.
What you need to do is create an operator called << that takes an object that cout is (ostream) and a PersonInfo object and then writes the various bits of the PersonInfo to cout.
So I've been set a task to create a temperature converter in C++ using this equation:
Celsius = (5/9)*(Fahrenheit – 32)
and so far I've come up with this (I've cut out the 10 lines worth of comments from the start so the code posted begins on line 11, if that makes any sense)
#include <iostream>
#include <string>
#include <iomanip>
#include <cmath>
using namespace std;
int main ()
{
float celsius;
float farenheit;
std::cout << "**************************" << endl;
std::cout << "*4001COMP-Lab5-Question 1*" << endl;
std::cout << "**************************" << endl << endl;
std::cout << "Please enter a temperature in farenheit: ";
std::cin >> farenheit >> endl;
std::cout << "Temperature (farenheit): " << endl;
std::cout << "Temperature (celsius): " << celsius << endl;
std::cin.get();
return 0;
}
Everytime I try to run this program I get a heap of errors with this one appearing every time:
1>m:\visual studio 2010\projects\week 5\week 5\main.cpp(26): error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::basic_istream<_Elem,_Traits>' (or there is no acceptable conversion)
I've tried everything I can think of to get rid of this error but it reappears every time, any idea on how to fix this?
std::cin >> farenheit >> endl;
This statement is invalid. remove >> endl from it.
std::cin >> farenheit ;
This statement is only valid when you cout something. Like here.
std::cout << farenheit << endl ;
The reason is that endl is the end-line character used to output a new line. So only the output stream accepts it. You can look up more about return values and prototypes of cin and cout here.
http://en.cppreference.com/w/cpp/io
std::endl is actually a function and the operator to stream into it is not defined. Yes it's a confusing error message as it is complaining about the LHS not the RHS.
Its implementation is something like:
namespace std {
std::ostream& endl( std::ostream& os )
{
os << '\n';
os.flush();
return os;
}
}
Streaming has then defined something like this:
namespace std {
std::ostream & operator<<( std::ostream & os, (std::ostream& *)(std::ostream&) func )
{
return func(os); // or is it (*func)(os)
}
}
It's actually quite a "powerful" feature of iostream, because you can then write a function with that signature and stream the function into your stream to do stuff with the iostream.
That is in fact a similar concept as to how the <iomanip> library also works (although that uses objects).