Why this usage string with ostream cause stackoverflow? - c++

I just wondering why this code is incorrect ? It constantly call Foo constructor and cause stack overflow after sometime.
#include <iostream>
using namespace std;
class Foo
{
std::string str;
public:
Foo(const string& s) : str(s)
{
cout << "Foo constructor" << endl;
}
friend ostream& operator<<(ostream& os,const Foo& foo);
};
ostream& operator<<(ostream& os,const Foo& foo)
{
os << foo.str;
return os;
}
int main()
{
Foo foo{"Hello"};
cout << foo;
cin.get();
}
I know, I know it is ok to write
cout << foo.str << endl;
or os << foo.str.c_str();
but I want to know why this error happens..

The program use std::string and its output operator but does not include the header <string>: when using <string> you need to include that header. The fact that std::string seems to be defined by including <iostream> is insufficient. It is also not portable: a different implementation may choose to only declare but not defined std::string (a declaration is needed, though, as some IOStream members to use the type std::string).
If the output operator for std::string isn't found, the expression
out << foo.str
is interpreted as as
out << Foo(foo.str)
as there is an output operator for Foo. Of course, that does result in an infinite recursion.

Related

Friend function defining an ostream operator

I would like to define an ostream operator to let me easily output variables of type alglib::complex. To provide a working example without including the alglib library I'll instead overload the output of complex<double> below (this clarification because of an earlier version of the question). In the header file "my_class.h" I have
using namespace std;
#include <complex>
#include <iostream>
class my_class {
public:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
void output(complex<double>);
my_class() {}
~my_class() {}
};
And in the source file "my_class.cpp" I have
#include "my_class.h"
void my_class::output(complex<double> cd) {
cout << cd << endl;
}
Finally I have a main method file "run_my_class.cpp":
#include "my_class.h"
int main(int argc, const char* argv[]) {
my_class obj;
complex<double> cd=complex<double>(1.0,-1.0);
obj.output(cd);
}
I try to compile using
g++ -c my_class.cpp
but this gives me the error
my_class.h:9:62: error: ‘std::ostream& my_class::operator<<(std::ostream&, std::complex<double>)’ must take exactly one argument
ostream& operator << (std::ostream& os, complex<double> a) {
However, if I define the operator as a friend, namely friend ostream& operator << (std::ostream& os, complex<double> a), it compiles and I compile the main method:
g++ run_my_class.cpp my_class.o -o run_my_class
And it works as it should. However this is not what it seems the friend keyword is for. Is there a better way to make this work?
Since operator << will be called on an std::ostream, you cannot define this procedure as a member function for my_class, you have to define it as a global function, since it's an operation for std::ostream, not my_class.
By putting the friend keyword into the declaration, you are saying that you want to declare the operator << as a friend global function (not a member function!). The C++ standard lets you put the definition of the friend function there, but it won't be a member function. It is the same as the following, which is more clear:
#include <complex>
#include <iostream>
class my_class {
public:
friend ostream& operator << (std::ostream& os, complex<double> a);
void output(complex<double>);
my_class() {}
~my_class() {}
};
std::ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
As it was already pointed out in the comments, the usage of friend is not necessary here.
Irrelevant to the question, but please be aware that resolving namespaces in a header file is generally a really-really bad idea, since all other files including it will implicitly resolve that namespace too. It can easily lead to vexing compilation errors in the long run.
I wouldn't call it a better way but a more clear way.
Here's your stream operator again:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
Its first parameter is the output stream. Since you do not have access to the output stream, you can't use the output stream operator as a member function unless you make it a friend of the class.
If you want to want to avoid using friend you can always define it as a function external to the class, and that is the most common way.

Why I cannot put this operator overload in the same namespace as the struct?

I have the following code:
#include <iostream>
#include <vector>
namespace X {
std::ostream& operator<<(std::ostream& os,const std::vector<double>& v){
for (int i=0;i<v.size();i++){os << v[i] << " ";}
return os;
}
namespace Y {
struct A {std::vector<double> x;};
std::ostream& operator<<(std::ostream& os,const A& a){
os << a.x << std::endl;
return os;
}
}
}
using namespace X;
int main(int argc, char** argv) {
std::vector<double> v(10,0);
std::cout << v << std::endl;
Y::A a;
std::cout << a << std::endl;
return 0;
}
The first overload works, but the second one does not. For some reason it cannot find the first one. I get the error:
no match for 'operator<<' (operand types are 'std::ostream
{aka std::basic_ostream<char>}' and 'const std::vector<double>')
os << a.x << std::endl;
^
I do not understand why I get this error. For example something like this seems to be completely valid:
namespace A {
void foo(){}
namespace B {
void bar(){foo();}
}
}
However, the only way to fix the above problem was to put the second overload also in X. Why is it not possible to have it in the same namespace as the struct (ie. X::Y)?
PS: I was reading on ADL and I found some related questions (e.g. this and this, but what I understood from reading this, the above should work.
In Argument Depended Lookup (or Koenig Lookup), compiler adds to the scope of visibility all symbols declared in parent scopes of each parameter.
Even if Y is "child namespace" of X, they are not related in terms of ADL. First of your parameters is type defined in std:: namespace, while second is local symbol (defined in the same namespace as the function itself).
Note, that because of reasons mentioned above, you will most likely get another error in this line:
std::cout << v << std::endl;
when compiler will not be able to find operator<< overloaded for std::vector<double> (because it lies inside namespace X).
To solve this, you can use:
using X::operator<<
inside namespace Y or move that overload.
If you are wondering, why foobar example works: that's because ADL (Argument Dependent Lookup) is about scope of parameters of functions, not functions themselves. In foobar code, ADL isn't applied.
As per other answers, I eventually deduced that ADL of operator<< was being impeded by the fact that it was taking place inside another operator<<.
Today's lesson: always write an operator<< overload in terms of a writer method :)
Here's the fix:
#include <iostream>
#include <vector>
namespace X
{
std::ostream& operator<<(std::ostream& os,const std::vector<double>& v){
for (int i=0;i<v.size();i++){os << v[i] << " ";}
return os;
}
namespace Y
{
struct A
{
std::vector<double> x;
void write(std::ostream&os) const {
os << x << std::endl;
}
};
std::ostream& operator<<(std::ostream& os,const A& a)
{
a.write(os);
return os;
}
}
}
using namespace X;
int main(int argc, char** argv)
{
std::vector<double> v(10,0);
std::cout << v << std::endl;
X::Y::A a;
std::cout << a << std::endl;
return 0;
}
As simple as this: In order to overload a function the overloaded version have to lives in the same nemaspace, otherwise, is a completely different function. The name of the function (for the compiler) is the complete path from the global namespace to the function itself.
::function_at_global_namespace();
Namespace::function_name(); // Some funtion within a namespace;
Namespace_1::function_name(); // Some other function within another namespace;
So,
Standar std::ostream& operator<< lives in std namespace, you are not overloading that operator, Just defining anotherone in namespace X.
As pointed by #0x499602D2 you must use X::operator<< in namespace Y in order to call that version of the operator.
std::ostream& std::operator<< and std::ostream& X::operator<< are diferent functions.
In following code none of the foo versions are overloading either.
// What version of foo gets called? A::foo, or B::foo?
namespace A {
void foo(){cout << "A::foo" << endl;}
namespace B {
void foo(){ cout << "B::foo" << endl;}
void bar(){foo();}
}
}
namespace C { void foo(int a) { cout << "C:foo" << endl; } }

Operator Overloading: Ostream/Istream

I'm having a bit of trouble with a lab assignment for my C++ class.
Basically, I'm trying to get the "cout << w3 << endl;" to work, so that when I run the program the console says "16". I've figured out that I need to use an ostream overload operation but I have no idea where to put it or how to use it, because my professor never spoke about it.
Unfortunately, I HAVE to use the format "cout << w3" and not "cout << w3.num". The latter would be so much quicker and easier, I know, but that's not my decision since the assignment necessitates I type it in the former way.
main.cpp:
#include <iostream>
#include "weight.h"
using namespace std;
int main( ) {
weight w1(6);
weight w2(10);
weight w3;
w3=w1+w2;
cout << w3 << endl;
}
weight.h:
#ifndef WEIGHT_H
#define WEIGHT_H
#include <iostream>
using namespace std;
class weight
{
public:
int num;
weight();
weight(int);
weight operator+(weight);
};
#endif WEIGHT_H
weight.cpp:
#include "weight.h"
#include <iostream>
weight::weight()
{
}
weight::weight(int x)
{
num = x;
}
weight weight::operator+(weight obj)
{
weight newWeight;
newWeight.num = num + obj.num;
return(newWeight);
}
TL;DR: how can I make the "cout << w3" line in main.cpp work by overloading the ostream operation?
Thanks in advance!
Make a friend function in your class
friend ostream & operator << (ostream& ,const weight&);
define it as :
ostream & operator << (ostream& os,const weight& w)
{
os<<w.num;
return os;
}
See here
class weight
{
public:
int num;
friend std::ostream& operator<< (std::ostream& os, weight const& w)
{
return os << w.num;
}
// ...
};
Alternately, make a to_string method that converts weight.num to string ;-)

Overloading I/O operator C++

I'm trying to overload the << operator. I'm expecting the output to be InitializingHello WorldOut but it is just outputting Hello World. I can't figure out what is wrong with my code. Thanks for your help.
#include <iostream>
using namespace std;
ostream &operator << (ostream &out, const char* &s)
{
out << "Initializing" << s << "Out";
return out;
}
void main() {
cout << "Hello World" << endl;
system("Pause");
}
"Hello World" is actually of type const char[12], which can decay into an r-value (temporary) of type const char *, but your function takes a reference to a const char*, and as you may know, you cannot bind a reference to a non-const r-value. So your operator is not called, but instead the standard ostream &operator << (ostream &out, const char* s) is.
PS. Please do not write void main(). It should be int main() unless you are in an embedded system (not likely).
There already is an overload for << with the exact same prototype. The compiler cannot decide which to use...
There is already a operator<< for const char* defined in the standard library, which is used in the output. Your overload is not used because the temporary string literal cannot be bound to the non-const reference in the operators second parameter.
If you remove the reference or make it const, then your operator is called. It doesn't even conflict with the one in your standard library, since that one is implemented as a function template. Yours is not, and non-templated functions are preferred by the compiler.
If it is then called, it leads to a stack overflow because out << "Initializing" immediately calls the same operator again recursively.
rodrigo pointed out that the type of a string literal is const char[x], and I had an evil idea:
#include <iostream>
using namespace std;
template<int len>
ostream &operator << (ostream &out, const char (&s)[len])
{
out << ((const char*)"Initializing") << ((const char*)s) << ((const char*)"Out");
return out;
}
int main() {
cout << "Hello World" << endl;
}
http://ideone.com/7wCNy
I think that since the left hand side is in the std namespace, it's using the function ostream& std::operator << (ostream &out, const char* s) that's defined in the std namespace instead of yours in the global namespace. If you were to try to put yours into the std namespace, you'd get a linker error. Your only real hope is to change the types of one side or the other, probably by making a wrapper around them.
struct charptr {
const char* ptr;
charptr(const char* p) :ptr(p) {}
};
ostream &operator << (ostream &out, const charptr &s)
{
out << "Initializing" << s.ptr << "Out";
return out;
}
int main() { //int main, not void
cout << charptr("Hello World") << endl;
system("Pause");
}

Function that prints something to std::ostream and returns std::ostream?

I want to write a function that outputs something to a ostream that's passed in, and return the stream, like this:
std::ostream& MyPrint(int val, std::ostream* out) {
*out << val;
return *out;
}
int main(int argc, char** argv){
std::cout << "Value: " << MyPrint(12, &std::cout) << std::endl;
return 0;
}
It would be convenient to print the value like this and embed the function call in the output operator chain, like I did in main().
It doesn't work, however, and prints this:
$ ./a.out
12Value: 0x6013a8
The desired output would be this:
Value: 12
How can I fix this? Do I have to define an operator<< instead?
UPDATE: Clarified what the desired output would be.
UPDATE2: Some people didn't understand why I would print a number like that, using a function instead of printing it directly. This is a simplified example, and in reality the function prints a complex object rather than an int.
You can't fix the function. Nothing in the spec requires a compiler to evaluate a function call in an expression in any particular order with respect to some unrelated operator in the same expression. So without changing the calling code, you can't make MyPrint() evaluate after std::cout << "Value: "
Left-to-right order is mandated for expressions consisting of multiple consecutive << operators, so that will work. The point of operator<< returning the stream is that when operators are chained, the LHS of each one is supplied by the evaluation of the operator to its left.
You can't achieve the same thing with free function calls because they don't have a LHS. MyPrint() returns an object equal to std::cout, and so does std::cout << "Value: ", so you're effectively doing std::cout << std::cout, which is printing that hex value.
Since the desired output is:
Value: 12
the "right" thing to do is indeed to override operator<<. This frequently means you need to either make it a friend, or do this:
class WhateverItIsYouReallyWantToPrint {
public:
void print(ostream &out) const {
// do whatever
}
};
ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
obj.print(out);
}
If overriding operator<< for your class isn't appropriate, for example because there are multiple formats that you might want to print, and you want to write a different function for each one, then you should either give up on the idea of operator chaining and just call the function, or else write multiple classes that take your object as a constructor parameter, each with different operator overloads.
You want to make MyPrint a class with friend operator<<:
class MyPrint
{
public:
MyPrint(int val) : val_(val) {}
friend std::ostream& operator<<(std::ostream& os, const MyPrint& mp)
{
os << mp.val_;
return os;
}
private:
int val_;
};
int main(int argc, char** argv)
{
std::cout << "Value: " << MyPrint(12) << std::endl;
return 0;
}
This method requires you to insert the MyPrint object into the stream of your choice. If you REALLY need the ability to change which stream is active, you can do this:
class MyPrint
{
public:
MyPrint(int val, std::ostream& os) : val_(val), os_(os) {}
friend std::ostream& operator<<(std::ostream& dummy, const MyPrint& mp)
{
mp.os_ << mp.val_;
return os_;
}
private:
int val_;
std::ostream& os_
};
int main(int argc, char** argv)
{
std::cout << "Value: " << MyPrint(12, std::cout) << std::endl;
return 0;
}
You have two options. The first, using what you already have is:
std::cout << "Value: ";
MyPrint(12, &std::cout);
std::cout << std::endl;
The other, which is more C++-like, is to replace MyPrint() with the appropriate std::ostream& operator<<. There's already one for int, so I'll do one just a tad more complex:
#include <iostream>
struct X {
int y;
};
// I'm not bothering passing X as a reference, because it's a
// small object
std::ostream& operator<<(std::ostream& os, const X x)
{
return os << x.y;
}
int main()
{
X x;
x.y = 5;
std::cout << x << std::endl;
}
There's no way to do what you're expecting there because of the order the functions are evaluated in.
Is there any particular reason you need to write directly to the ostream like that? If not, just have MyPrint return a string. If you want to use a stream inside MyPrint to generate the output, just use a strstream and return the result.
First, there is no reason not to pass in the ostream by reference rather than by a pointer:
std::ostream& MyPrint(int val, std::ostream& out) {
out << val;
return out;
}
If you really don't want to use std::ostream& operator<<(std::ostream& os, TYPE), you can do this:
int main(int argc, char** argv){
std::cout << "Value: ";
MyPrint(12, std::cout) << std::endl;
return 0;
}
After changing the pointer to a reference, you can do this:
#include <iostream>
std::ostream& MyPrint(int val, std::ostream& out) {
out << val;
return out;
}
int main(int, char**) {
MyPrint(11, std::cout << "Value: ") << std::endl;
return 0;
}
The syntax for MyPrint is essentially that of an unrolled operator<< but with an extra argument.
In your case the answer is obviously:
std::cout << "Value: " << 12 << std::endl;
If that isn't good enough, please explain what output you want to see.