C++ operator<< and >> methods in the header file, done very wrong - c++

I have this code in my header file and Ive got loads of errors on the ostream and istream lines. One error is "missing ";" before "&"" and im confuzzled, im new to this sorry
#pragma once
class ArrayIntStorage
{
public:
void readFromFile();
bool setReadSort(bool);
void sortStd();
void sortOwn();
ArrayIntStorage(void);
~ArrayIntStorage(void);
};
ostream& operator<< (ostream &out, const ArrayIntStorage &a);
istream& operator>> (istream &in, ArrayIntStorage &b);
thanks in advance

Looks like you just need to do
#include <ostream>
#include <istream>
then place a std namespace qualifier in front of them on those lines, ie:
std::ostream& operator<<(std::ostream& out,...)

It's not clear to me the context this code appears in but the error suggests that these declarations appear before ostream and istream are defined.
Are you including the proper header files in the proper order?

You omitted includes:
#include <istream>
#include <ostream>
Note: all the standard types like istream, ostream live within a namespace called std. So in order to be able to use them you need to either:
prefix them with std:: or
use the namespace (using namespace std;). This is a very bad practice for a header file as it may cause naming clashes in the header files that are included later on.

Add the iostream include and Put the method prototype inside the class and declare it friend. I can't give more details since I am replying from my mobile.
Here is a link: Operator-Overloading/Classlevelostreamoperatorandistreamoperator.htm">http://www.java2s.com/Tutorial/Cpp/0200_Operator-Overloading/Classlevelostreamoperatorandistreamoperator.htm

Related

std::ostream recognize without defining header

I created this code:
Main.cpp
#include <iostream>
#include "Quote.h"
int main()
{
derived().print(std::cout);
getchar();
return 0;
}
Quote.h
#pragma once
#include <string>
class base {
public:
std::string name() { return basename; }
virtual void print(std::ostream &os) { os << basename; }
private:
std::string basename = "abc";
};
class derived : public base {
public:
void print(std::ostream &os) { base::print(os); os << " " << i; }
private:
int i = 0;
};
If I don't include the iostream header file in Main.cpp, as expected, std::cout is not recognized. My question is: Why there's no problem with the use of std::ostream in Quote.h if iostream is not included?. Either cout as ostream are defined in the aforementioned library, why the cout use is a problem and ostream not?
I'm using VS 2017, in case this info is important.
All existing answers concentrate on #include <string>. I'd like to point at another side. Consider slightly modified version:
quote.h:
#pragma once
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
main.cpp:
#include <iostream>
#include "quote.h"
int main()
{
std::cout << Quote{};
}
As you see #include <string> is commented out, quote.h still doesn't include iostream and the program still compiles. It does because only source files (.cpp, or translation units) are directly compiled. Headers are literally included. Now if we literally include quote.h in main.cpp we get:
#include <iostream>
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
int main()
{
std::cout << Quote{};
}
(online)
It's what actually gets compiled. Notice everything is alright here, #include <iostream> before std::ostream usage.
And as was correctly pointed in comment to another answer, this is an example why it's important to always maintain self-sufficient headers that include all headers they depend on.
As #Evgeny pointed out in the comment, please check recommendations about organising our includes.
The header <string> declares an output operator using std::ostream. It seems the implementation you are using does so in a way making std::ostream generally available.
The C++ standard defines which headers make which declarations available at least. It doesn’t prohibit against additional names being made available. Different implementations may choose to not make the declarations available. I have tried making strictly only mandated declarations available in my implementation but this turns out to be not quite as simple as it sounds.
You include <string> in your header file. If you go to the string header you will see the first lines as (in VS2017):
// string standard header
#pragma once
#ifndef _STRING_
#define _STRING_
#ifndef RC_INVOKED
#include <istream> <----- here
#include <xstring_insert.h>
and going to the istream header:
// istream standard header
#pragma once
#ifndef _ISTREAM_
#define _ISTREAM_
#ifndef RC_INVOKED
#include <ostream> <-- here
which I think already answers your question. However, this is implementation dependent and you should not rely on this but include explicitly the iostream header.
The header <string> provides the extraction and insertion operators for std::string, so it has to make sure that std::ostream is at least forward-declared; your code only uses a reference to ostream, for which a forward declaration suffices, plus the aforementioned insertion operator, which is correctly declared.
So, strictly speaking, all that is needed by your header is already provided by the header <string>, although I'd probably explicitly include <iosfwd> for clarity.
Why there's no problem with the use of std::ostream in Quote.h if <iostream> is not included?
<iostream> get #included indirectly.
It's best not to rely on such indirection #includes. You can't count on it being true on all platforms. It may even change from debug build to release build.
When you want to use a class or a function, it's best to lookup the standard for the header that's supposed to provide the definition of the class and the declaration of the function, and #include the header directly in your file.

Template overload of insertion operator >> causing cin issue

so I've got a project where I am inserting user entered data into classes. So I've overloaded the >> operator. Because I have classes with similar structures, I made the overload a template to try to save time. Making this template overload a friend of the classes seems to work, as I get no compile errors.
My ClassDefs.h:
// ClassDefs.h
using namespace std;
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <tuple>
#include <map>
#include <typeinfo>
class measurement {
//friends
template<class measT> //measT are other similar measurement classes
friend istream & operator >> (istream&, measT&);
private:
string words;
public:
//constructors and things like that here
};
template<class measT>
istream& operator >> (istream& is, measT& meas) {
//a series of checks to ensure user entry is valid
//enter user entry into private data
//e.g.
string line;
getline(is,line);
meas.words = line;
return is;
}
The problem comes when using cin >> foo in main - I get a warning caption saying "more than one operator >> matches these operands". Accompanied by:
error C2593: 'operator >>' is ambiguous
This makes sense, but my crude understanding of overloads was that they allow you to use different types with that operator and the compiler "understands" which definition to use for each situation.
My main.cpp:
// main.cpp
#include "ClassDefs.h"
int main(){
string entry;
cin >> entry;
^^ error here
return 0;
}
I have looked around and seen things involving explicit, inline, namespace (my using namespace std; seems dodgy) but I haven't seen anyone use this template overload arrangement and have this problem. I'm using Visual Studio 2015 Community.
Any help or advice would be greatly appreciated :)
So I solved this partially with the help of #user4581301 - I really needed to keep the >> overload a template so that I could use that parameter for a template exception class inside it.
It has become a bit convoluted but I thought I'd share in case anyone else is having issues overloading operators with templates.
Firstly I changed measurement from an abstract base class to a base class (so that it could be used as a template parameter) and changed the friend declaration inside to:
//ClassDefs.h
template <class measT>
friend istream& operator >> (istream&, measurement&);
Where measT was the type of measurement involved, to be used as the parameter for the exception class.
Then later on in the header file, >> was overloaded with the definition:
//ClassDefs.h
template<class measT>
istream& operator >> (istream& is, measurement& meas) {
//take user input
//do checks on it, throw Exception<measT> depending on which set of
exceptions are relevant
}
And most importantly I wasn't sure how to use an operator with a template parameter but it turns out you can do it explicitly:
//ClassDefs.h
template<class measT>
measT userNewMeas() { //function to take user input and make into a type
// of measurement
try { ::operator>><measT> (cin,newMeas); }
catch (Exception<measT>& error) {
cout << error << endl; // this output depends on which exception
// was called
}
And now I can use template userNewMeas() in main.cpp with template >> and template Exception. The goal is probably hard to see for everyone but I was trying to overload >> for any measurement type, and have one Exception class containing different error messages to be thrown depending on which measurement was being entered.

Why is #include <string> preventing a stack overflow error here?

This is my sample code:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
string figName;
public:
MyClass(const string& s)
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
ostream& operator<<(ostream& ausgabe, const MyClass& f)
{
ausgabe << f.getName();
return ausgabe;
}
int main()
{
MyClass f1("Hello");
cout << f1;
return 0;
}
If I comment out #include <string> I don't get any compiler error, I guess because it's kind of included through #include <iostream>. If I "right-click --> Go to Definition" in Microsoft VS they both point to the same line in the xstring file:
typedef basic_string<char, char_traits<char>, allocator<char> >
string;
But when I run my program, I get an exception error:
0x77846B6E (ntdll.dll) in OperatorString.exe: 0xC00000FD: Stack overflow (Parameter: 0x00000001, 0x01202FC4)
Any idea why I get a runtime error when commenting out #include <string>? I'm using VS 2013 Express.
Indeed, very interesting behavior.
Any idea why I get I runtime error when commenting out #include <string>
With MS VC++ compiler the error happens because if you do not #include <string> you won't have operator<< defined for std::string.
When the compiler tries to compile ausgabe << f.getName(); it looks for an operator<< defined for std::string. Since it was not defined, the compiler looks for alternatives. There is an operator<< defined for MyClass and the compiler tries to use it, and to use it it has to convert std::string to MyClass and this is exactly what happens because MyClass has a non-explicit constructor! So, the compiler ends up creating a new instance of your MyClass and tries to stream it again to your output stream. This results in an endless recursion:
start:
operator<<(MyClass) ->
MyClass::MyClass(MyClass::getName()) ->
operator<<(MyClass) -> ... goto start;
To avoid the error you need to #include <string> to make sure that there is an operator<< defined for std::string. Also you should make your MyClass constructor explicit to avoid this kind of unexpected conversion.
Rule of wisdom: make constructors explicit if they take only one argument to avoid implicit conversion:
class MyClass
{
string figName;
public:
explicit MyClass(const string& s) // <<-- avoid implicit conversion
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
It looks like operator<< for std::string gets defined only when <string> is included (with the MS compiler) and for that reason everything compiles, however you get somewhat unexpected behavior as operator<< is getting called recursively for MyClass instead of calling operator<< for std::string.
Does that mean that through #include <iostream> string is only included partly?
No, string is fully included, otherwise you wouldn't be able to use it.
The problem is that your code is doing an infinite recursion. The streaming operator for std::string (std::ostream& operator<<(std::ostream&, const std::string&)) is declared in <string> header file, although std::string itself is declared in other header file (included by both <iostream> and <string>).
When you don't include <string> the compiler tries to find a way to compile ausgabe << f.getName();.
It happens that you have defined both a streaming operator for MyClass and a constructor that admits a std::string, so the compiler uses it (through implicit construction), creating a recursive call.
If you declare explicit your constructor (explicit MyClass(const std::string& s)) then your code won't compile anymore, since there is no way to call the streaming operator with std::string, and you'll be forced to include the <string> header.
EDIT
My test environment is VS 2010, and starting at warning level 1 (/W1) it warns you about the problem:
warning C4717: 'operator<<' : recursive on all control paths, function will cause runtime stack overflow

`operator>>' is not a member of `Instance'

I have the InstancePool class (part of it below) with the Instance.h header included, but I get the error in the title in the operator>> function of InstancePool.
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <stdlib.h>
using namespace std;
#include "Instance.h"
#include "InstancePool.h"
istream &operator >> (istream &in , InstancePool &ip) {
ip.Instances->clear();
string input;
getline(in , input);
while (!in.eof()) {
Instance inst;
Instance::operator >>(in , inst); // <- line giving me the error
ip.Instances->push_back(inst);
getline(in , input);
}
}
The InstancePool operator>> function is a 'friend' function BTW, and so is the same function in Instance. Probably I'm trying to access the Instance 'operator>>' in the wrong way but I'll be damned if I know the correct one...
Any help?
Friend functions aren’t member functions, you cannot explicitly qualify the function’s name the way you did because it’s simply not inside a namespace called Instance.
The good news is: you don’t need to. Just call it normally:
in >> inst;
There are more bugs in your code, though. First off, while (in.eof()) will result in an infinite loop when there’s an error while reading – never do this.
Second of all, you’re reading and discarding lines with getline. This is probably not what you want to do, right? Do you want to read each instance from the line or directly from the input stream?

What do I need to include in my header file for ostream

When I try to compile my program the compiler complains about this line in a .h file that I #included.
ostream & Print (ostream & stream);
How can this be fixed?
If you #include <ostream>, ostream will be defined in the std namespace:
#include <ostream>
// ...
std::ostream & Print (std::ostream & stream);
Use 'using' if you don't want to pull the whole std namespace, eg :
#include <iosfwd>
using std::ostream;
Minimal code for this declaration to compile:
#include <iosfwd>
using namespace std;