Overloading operator<< to work for string - c++

In the following code:
using namespace std;
//ostream& operator<< (ostream& out,const string & str)
//{
// out << str.c_str();
// return out;
//}
int _tmain(int argc, _TCHAR* argv[])
{
ofstream file("file.out");
vector<string> test(2);
test[0] = "str1";
test[1] = "str2";
ostream_iterator<string> sIt(file);
copy(test.begin(), test.end(), sIt);
file.close();
return 0;
}
what is the proper way to overload operator << to make
copy(test.begin(), test.end(), sIt); work.
What am I missing?
EDIT: I'm just stupid... forgot to include "string" header
Thank you!

You do not need to overload operator<< to work with strings, it already knows how to handle them.
std::copy( test.begin(), test.end(),
std::ostream_iterator<std::string>( file, "\n" ) );
will produce:
str1
str2
Is there anything different/special that you want to be done there?

As David already pointed out, there is already a operator<< for strings, so you don't have to provide one. Should you really want to define your own overload anyway, then there's a slight problem, because actually you are not allowed to do that. operator<< is defined in the std namespace, so if you want to have a usable overload for std::string (the version in most implementations is a template function, so there is a potential overload), you'll have to do this in the std namespace too (this because of the ways ambiguities and overloads are resolved in C++, there are some caveats here) . For example:
namespace std {
ostream& operator<< (ostream& out,const string & str)
{
out << "A STRINGY:" << str.c_str();
return out;
}
}
However, adding stuff into the std namespace is not allowed for ordinary users, because it might have implementation specific effects that are unforeseeable and could break all kinds of stuff inside the standard library. Also, there is no guarantee, that your implementation of the standard library has a overloadable operator<<. This means, it could work or it could not.

Lemme just add the link from cplusplus.com for future reference
http://www.cplusplus.com/reference/algorithm/copy/

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.

Is the std::istream type EqualityComparable?

My question would have a boolean answer: yes or not. Whichever it would be, can someone explain how the following code is compiled by both GNU-g++ 4.9.2 and clang 3.5, while GNU-g++ 5.1.1 no longer accepts it, claiming that there is no matching operator==?
And how it could be changed, for this last compiler, in order to have the same results i.e. to have the operator>> able to distinguish, in such a simple way, whether
it is called by the standard input stream or by something else?
# include <iostream>
# include <fstream>
struct S {};
std::istream& operator >> (std::istream& i, S& s)
{
if(i == std::cin) std::clog << "this is standard input\n";
else std::clog << "this is some other input stream\n";
return i;
}
int main(int narg, const char ** args)
{
S s;
std :: cin >> s;
std::ifstream inp(args[1]);
inp >> s;
}
// to be executed with the name of an existing
// disk file on the command line....
No. There's no operator== that operates on std::istream objects.
Your being able to compare two std::istreams is an unfortunate consequence caused by the conversion function of std::istream, specifically operator void*. In the expression i == std::cin, both i and std::cin are implicitly converted to void*, and the resulting values are compared. This is not really meaningful. This conversion function was removed in C++11 (replaced by an explicit conversion function, which won't be called in this situation), so if you enable the C++11 mode, the code will not compile.
As is stated here, if you want to check whether the reference i refers to std::cin, you can use &i == &std::cin.
Standard C++ streams don't have ==, >, < operators because they are not very meaningful in that context: what should "stream a is > than stream b" mean?
However, it shouldn't matter what type of istream you're dealing with: as long as you're not using specific methods defined in descendant classes (like is_open), base methods are shared (extracting, for instance). Whether you're extracting a string from a istringstream or a ifstream, you just do in >> str and let polymorphism take action.
If you really want to know the polymorphic type of the istream, you can use typeid or, simply, function overloading. In your case, with RTTI(typeid)
if ( typeid(in) == typeid(std::cin) )
// cin
else
// another istream type
Using overloading:
std::istream& operator >> (std::istream& i, S& s)
{
std::clog << "this is standard input\n";
return i;
}
std::ifstream& operator>>(std::ifstream& i, S& s)
{
std::clog << "this is some file input stream\n";
return i;
}

Why can I overload istream's operator>> for strings?

Suppose I wanted operator>> to extract entire lines from an istream instead of whitespace-separated words. I was surprised to see that this, although horrible, actually worked:
#include <iostream>
#include <string>
namespace std {
istream &operator>>(istream &is, string &str) {
getline(is, str);
}
}
int main() {
std::string line;
std::cin >> line;
std::cout << "Read: '" << line << "'\n";
}
If I type multiple words into stdin, it actually does call my operator and read an entire line.
I would expect this definition of operator>> to conflict with the official one, producing a link error. Why doesn't it?
Edit: I thought maybe the real operator>> was a template, and non-template functions take precedence, but this still works just as well:
namespace std {
template<typename charT>
basic_istream<charT> &operator>>(basic_istream<charT> &is, basic_string<charT> &s) {
getline(is, s);
}
}
It happens to work because the official template is less specific (there are additional template arguments).
However it is Undefined Behaviourâ„¢. You are only permitted to provide overloads of standard library symbols for your own types. If you come across another standard library that will define extra overloads (it may), it will stop working and you won't know why.

iostream limit max number of chars to read

Learning C++ with help of Bruce Eckel "Thinking in C++". Stuck in exercise 05 of chapter "Iostreams":
Text of exercise
We know that setw( ) allows for a minimum of characters read in, but what if you wanted to read a
maximum? Write an effector that allows the user to specify a maximum number of characters to
extract. Have your effector also work for output, in such a way that output fields are truncated, if
necessary, to stay within width limits.
I understand how to create manipulators both without and with parameter (which one is called effectors in the book terminology). But do not understand how to limit maximum number of characters to extract. std::ios_base::width specifies the minimum number of characters.
Shoud I do some tricks with underlying streambuf object?
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
using namespace std;
class fixW{
char* chrP;
char str[1024];
size_t Max;
public:
fixW(char* p,size_t m=25):chrP(p),Max(m){}
friend istream& operator >>(istream& is,fixW fw){
is >>fw.str;
size_t n=strlen(fw.str);
cout <<" n= "<<n << endl;
if(n>=25){
fw.str[fw.Max]='\0';
}
strcpy(fw.chrP,fw.str);
return is;
}
friend ostream& operator<<(ostream& os, fixW fw){
for(size_t i= 0; i<fw.Max; ++i){
fw.str[i] = fw.chrP[i];
}
fw.str[fw.Max]='\0';
return os <<fw.str;
}
};
int main(){
char s[80];
cin >> fixW(s,25);
cout << s << endl;
cout << fixW(s,10)<<endl;
cout << s <<endl;
return 0;
}
Its not a perfect solution (but I can't think of another way at the moment without reading the iostream library).
Say you manipulator is:
class MaxFieldSize {/*STUFF*/};
When you write the stream operator(s) you write a slightly funky one that does not return an actual stream (but rather returns a stream with a wrapper around it).
MaxFieldWdithStream operator<<(std::ostream&, MaxFieldSize const& manip);
Now you overload all the stream operator of this class to truncate their input before returning a normal stream object.
class MaxFieldWithStream { std::ostream& printTruncatedData(std::string& value);};
Then all you need is the generic overloads:
template<typename T>
std::ostream& operator<<(MaxFieldWithStream& mfwstream, T const& value)
{
std::stringstream trunStream;
trunStream << value;
return mfwstream.printTruncatedData(trunStream.substr(0, mfwstream.widthNeeded));
}
// You will probably need another overload for io-manipulators.
I would also add a conversion operator that converts MaxFieldWithStream to std::iostream automatically so that if it is passed to a function it still behaves like a stream (though it will loose its max width property).
class MaxFieldWithStream
{
std::ostream& printTruncatedData(std::string& value);};
operator st::ostream&() const { return BLABLAVLA;}
};

Support for const_string in std::ostream operator <<

I'm currently using the very clever package boost::const_string until http://libcxx.llvm.org/ is available pre-packaged on Ubuntu or GCC make its __versa_string (in header ext/vstring.h) its default string implementation. libcxx's std::string aswell as __versa_string uses _small-string optimization (SSO) by default. Default support for outputting to an std::ostream is lacking however. The code
#include <iostream>
#include <boost/const_string.hpp>
const_string<char> x;
std::cout << x << endl;
does not work unless we force x into a c-string via c_str() which becomes
std::cout << x.c_str() << endl;
which compiles and works as expected. I added the following line to const_string.hpp
template <typename T>
inline std::ostream & operator << (std::ostream & os, const boost::const_string<T> & a)
{
return os.write(a.data(), a.size());
}
This should improve performance over x.c_str() because size() is already known and does not need to be calculated by searching for NULL as in c_str(). I works for me but I am uncertain whether it works all cases. Have I missed something?
Have I missed something?
Yes, just include const_string/io.hpp. All it does however is:
return o << std::basic_string<char_type, traits_type>(s.data(), s.size());
It seems that this could have implications based on the locale and/or facets applied to the stream for strings vs just writing the straight data as you're doing.
It would be less performant, but what about creating a std::string from the const_string and using << to insert that into the stream?
No (you have not missed anything, afaik). If your aim is not to copy over content, str.data() is the way to go.