Compiler error for using operator '>>' with ifstream - c++

I am trying to use a custom template for IO, and I getting an error :
"error C2678: binary '>>' : no operator found which takes a left-hand operand of
type 'std::ifstream' (or there is no acceptable conversion)"
I have searched and found only suggestions to try including more headers, and have tried including: string, fstream, iostream, istream, vector. I can use an fstream.get(), but I am trying to get space delimited strings. (The format of my file is lines like this: "String1 = String2")
Here is my code:
template <typename OutType>
OutType Read(std::ifstream& in)
{
OutType out;
in >> out;
return out;
}
Any suggestions are very much appreciated! Thanks!
(P.S. Not sure if it will matter for compiler considerations, but I am using Visual Studio 2013.)

The problem is your OutType (which you have not shown us) has no operator>>(istream&, OutType&). You need to define one for every possible OutType.

How you are expecting OutType is known to >> operator? It understands primitives like int,char, etc., but if you want to make OutType available to << you should overload the operator.

Related

C++: Unwanted Conversions between ostream and ofstream

I've been working on a personal dictionary application which can help you remembering words you learnt. It is operated via the CLI (just don't question this, it's kinda just a test and I got a weird passion for CLI apps). So, of course I am using ostreams for writing information on the CLI. I am used to write operator<< overloads (for ostreams) for every class so that I can build up a multi-level output system (basically every object can "speak" for itself).
In order to persist a dictionary object, I wanted to use ofstream and write a file with it. Naturally, I wrote operator<< overloads also for ofstream and in the same "layered" structure.
As a result, I have now two operator<< overloads in every class, like in "Dictionary":
ostream& operator<<(ostream&, const Dictionary&);
ofstream& operator<<(ofstream&, const Dictionary&);
(this is just the declaration in the header file)
Notice that it is very important that these both overloads do different things. I don't want to have some weird persistence-oriented special-format text on the CLI and also not user-friendly plain text in my file.
The problem is that, because of the inheritance structure of ostream and ofstream, ofstream is sometimes implicitely converted to ostream. And when this happens in the middle of my stack full of file output operations, the program suddenly jumps into the wrong overload and prints plain text in the file.
My question is simply: Is there a way to avoid or revert these unwanted implicit conversions in order to let my program jump into the right overloads? Or is there any other good way to fix this problem?
EDIT 1:
Someone pointed out in the comments that this is not an implicit converison. ofstream is sometimes "seen" as its base class ostream. The problem is that at some point the object "forgets" that it is an ofstream and loses all file-related information. From there on it is only an ostream and that's what I meant with the "conversion".
EDIT 2:
The exact point in the program where the "unwanted conversion" happens can be found here:
ofstream& operator<<(ofstream& of, const Section& s) {
return s.print_ofstream(of);
}
So this operator overoad calls "print_ofstream":
ofstream& Section::print_ofstream(ofstream& of) const {
of << "sec" << Util::ID_TO_STRING(section_id) << ":\n";
for (pair<Wordlist, Wordlist> pwl : translations) {
of << '{' << pwl.first << '=' << pwl.second << "}\n";
}
of << "#\n";
return of;
}
Note that "pwl" is a pair of two Wordlists, therefore pwl.first / pwl.second is a Wordlist. So, normally the line of << '{' << pwl.first << '=' << pwl.second << "}\n"; should call the ofstream operator<< overload in Wordlist. But it doesn't. Instead, the other overload method is called:
ostream& operator<<(ostream& o, const Wordlist& wl) {
return wl.print_ostream(o);
}
You have overloaded only the specific operator<< needed for streaming Dictionary, Section, Wordlist, etc objects to a std::ofstream, but std::ofstream inherits MANY other operator<<s from std::ostream, and those operators all take ostream& as input and return ostream& as output. So, for example, of << "sec" will return ostream& even though of is a std::ofstream, and then that ostream& is used for subsequent << calls until ; is reached. Those are the "implicit conversions" you are experiencing.
The real question is, WHY do you want operator<< to output different data depending on the type of std::ostream being written to? That goes against C++'s streaming model. If you really want that, you would have to change print_ofstream(ofstream&) to print_ostream(ostream&) and then dynamically detect the actual std::ostream derived type using dynamic_cast. Same with Wordlist, and any other classes that need it.
A simpler and safer option would be to just store a flag inside of your classes to control how their data should be output, regardless of the type of std::ostream being used. Then you can set that flag as needed. Maybe even define some helper I/O manipulators to set those flags while making << calls.

What is <<= operator in C++

I found following code in a legacy system.As it seems to be a "assign and left shift" but I see this code is copying a string to ws but I couldn't understand how ? I wonder if simple assignment would have been enough to copy one string to another then why someone would code like this ?
vector<string> unique_dirs;
......
......
......
std::wstring ws;
ws <<= unique_dirs[i];
Edit - I looked at the class implementation (c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xstring) . There is no such operator "<<=" overloaded in the class.
There is no such standard overload operator the left operand of which is std::wstring and the right operand is std::string. You should investigate the code where this operator was encountered that to find its definition.
By default :
ws <<= unique_dirs[i]
is the same as :
ws = ws << unique_dirs[i]
It is simply the Bitwise left shift assignment.
But in this case, it should be overloaded to work with strings.
Despite my comment that investigating the code would be easier than people guessing what is happening, here is my guess at a possible implementation, as you were wondering how it could be done - this could appear anywhere in the code, pretty much, providing it can be seen where it is being called, as it's not modifying any of the standard library classes:
std::wstring& operator<<=(std::wstring& out, const std::string& in) {
out += std::wstring(in.begin(), in.end());
return out;
}
My guess here is that as a string is being passed to a wstring, the operator is performing some kind of "widening" (a poor-mans conversion from char to wchar, disregarding encoding).
Why would you want this rather than using a straight assignment? Well, aside from ws = unique_dirs[i]; being a compilation error, it could provide you with a method of concatenating strings:
std::string hello("hello ");
std::string goodbye("goodbye");
std::wstring ws;
ws <<= hello;
ws <<= goodbye;
// ws now is L"hello goodbye"
As an aside, the above does not modify the standard library - it is not extending the std::basic_string class, it's simply providing an operator that takes two classes as parameters. So I'm not sure how it comes under "legality" with regards its usage. It is fairly horrific, however, and its usage is morally reprehensible.
Unless the <<= is overloaded, It is the bitwise left shift operator.
ws <<= unique_dirs[i]
means
ws = ws << unique_dirs[i]
Although I am doubtful about the logic behind how the code is using some string element in the vector for this purpose.

Defining the structure of a binary file in C++ 11

Since I have to work with files in binary a lot, I would like to have a more abstract way to do that, I have have to perform the same loop over and over:
write an header
write different kind of chunks ( with different set of values ) in a given order
write an optional closing header
Now I would like to break down this problem in small building blocks, imagine if I can write something like what the DTD is for the XML, a definition of what can possibly be in after a given chunk or inside a given semantic, so I can think about my files in terms of building blocks instead of hex values or something like that, also the code will be much more "idiomatic" and less cryptic.
In the end, there something in the language that can help me with binary files from this prospective ?
I'm not sure about C++11 specific features, but for C++ in general, streams make file I/O much easier to work with. You can overload the stream insertion (<<) and stream extraction (>>) operators to accomplish your goals. If you're not very familiar with operator overloading, chapter 9 of this site, which explains it well, along with numerous examples. Here's the particular page for overloading the << and >> operators in the context of streams.
Allow me to illustrate what I mean. Suppose we define a few classes:
BinaryFileStream - which represents the file you are trying to write to and (possibly) read from.
BinaryFileStreamHeader - which represents the file header.
BinaryFileStreamChunk - which represents one chunk.
BinaryFileStreamClosingHeader - which represents the closing header.
Then, you can overload the stream insertion and extraction operators in your BinaryFileStream to write and read the file (or any other istream or ostream).
...
#include <iostream> // I/O stream definitions, you can specify your overloads for
// ifstream and ofstream, but doing so for istream and ostream is
// more general
#include <vector> // For holding the chunks
class BinaryFileStream
{
public:
...
// Write binary stream
friend const std::ostream& operator<<( std::ostream& os, const BinaryFileStream& bfs )
{
// Write header
os << bfs.mHeader;
// write chunks
std::vector<BinaryFileStreamChunk>::iterator it;
for( it = bfs.mChunks.begin(); it != bfs.mChunks.end(); ++it )
{
os << (*it);
}
// Write Closing Header
os << bfs.mClosingHeader;
return os;
}
...
private:
BinaryFileStreamHeader mHeader;
std::vector<BinaryFileStreamChunk> mChunks;
BinaryFileStreamClosingHeader mClosingHeader;
};
All you must do then, is have operator overloads for your BinaryFileStreamHeader, BinaryFileStreamChunk and BinaryFileStreamClosingHeader classes that convert their data into the appropriate binary representation.
You can overload the stream extraction operator (>>) in an analogous way, though some extra work may be required for parsing.
Hope this helps.

Boost property tree issue when converting to Unicode

Ok, first off I'm not a C++ developer by nature; I've managed to put some stuff together and it works fine, but I'm sure through the eyes of an expert it looks like garbage =)
So I have a freeware app that I've made which uses Property Tree from the Boost libraries. I developed the entire app (in VS2010) with the Use Multi-Byte Character Set setting. I decided it was time to go through and update the app to support Unicode as there are some folks with complex character sets that I'd like to better support.
I went through the tedious process of changing all the references and calls to use wide strings, all the necessary conversions. However, I'm completely stumped at one point, the only two compiler errors I have left.
They both come from stream_translator.hpp (/boost/property_tree/), lines 33 and 36 (as noted below):
template <typename Ch, typename Traits, typename E, typename Enabler = void>
struct customize_stream
{
static void insert(std::basic_ostream<Ch, Traits>& s, const E& e) {
s << e; //line 33
}
static void extract(std::basic_istream<Ch, Traits>& s, E& e) {
s >> e; //line 36
if(!s.eof()) {
s >> std::ws;
}
}
};
The error at line 33 is:
Error 347 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::wstring' (or there is no acceptable conversion) {...}\boost_1_49_0\boost\property_tree\stream_translator.hpp 33 1
..and the error at line 36 is:
Error 233 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) {...}\boost_1_49_0\boost\property_tree\stream_translator.hpp 36 1
From what I've been able to walk backwards through, it's coming from within stream_translator.hpp ultimately beginning as a call to get a value [e.g. ptree.get("some.path", "default value here")]
I really have absolutely no idea how to resolve this issue and cannot seem to find anything online to help me understand what exactly the problem is. Any tips or info would be greatly appreciated.
EDIT
So I commented out everything relating to ptree until it would compile, then began adding them back in. It turns out I can call .get fine, it's get_child where the error # line 36 pops up (haven't done the other project yet, where the wstring issue is).
To simplify things, here is the effective sequence of the calls, which are fine until get_child is called:
boost::property_tree::ptree pt;
boost::property_tree::read_xml("Config.xml", pt);
int iAppSetting = pt.get("config.settings.AppSetting",1); //<- works fine
ptree ptt;
ptt = pt.get_child("config.Applications"); //<- adding this line causes the line 36 error
Guessing that your problem was the same I ran into... There are wide character versions of Boost.PropertyTree for unicode support.
For Config.xml that is setup like this:
<?xml version="1.0"?>
<Zoo>
<Monkey>
<Food>Bananas</Food>
</Monkey>
</Zoo>
Use code similar to this to parse it:
// Load up the property tree for wide characters
boost::property_tree::wptree pt;
boost::property_tree::read_xml("Config.xml", pt);
// Iterate
BOOST_FOREACH(wptree::value_type const& v, pt.get_child(L"Zoo"))
{
if( v.first == L"Monkey" )
{
wstring foodType = v.second.get<wstring>(L"Food");
}
}

Conversion problems in C++ (string expected)

I have a function that I cannot touch, Is a "log maker", It puts something to print in a file an show it up when I run the file. The problem is that the function only gets const string so if I want to print something I have to convert everything in this data type (I cannot use cout).
itoa & atoi functions are not standard functions so I cannot use it neither. C++ is very "special" with data types and doesn't accept conversions really easy, so this is my question:
How can I convert everytype of data into string for the log purposes?
Probably I should check data type on a function to convert things and returning them into a stringstream (witch I have to convert into a string, of course).
So, any advice on how to do that?
boost::lexical_cast encapsulates the use of ostringstream, so you
could use that. Otherwise, the code isn't that difficult:
template<typename T>
std::string
toString( T const& object )
{
std::ostringstream results;
results << object;
return results.str();
}
(There's no reason to use stringstream here; ostringstream is largely sufficient.
You can use
std::stringstream
or
boost lexical_cast<>
Yes, if you want arbitrary type in string representation stringstream intermediate sounds like a solution.
I assume the functions expects a const std::string & ?
Your approach with std::stringstream is correct. Alternatively you could simply write a toString() method for the class you wish to directly output. However, usually when one wants to output objects to a file, overloads the << operator for that particular type.