Difference between `cout << x` and `cout.operator <<(x)`? - c++

I've been trying to use for_each to print a vector of strings to cout. However, when formulating the statement I found that std::ostream::operator<<(const std::string &); is not defined leading to compiler errors. The following code illustrates the problem:
#include <iostream>
#include <string>
int main()
{
std::string message = "Hello World!\n";
// This works
std::cout << message;
// Compiler error
std::cout.operator <<(message);
}
I thought that both statements should appear identical to the compiler. Apparently they are not. So what is the difference then?
Solved
As Tomalak and Prasoon indicated I needed to call this function:
std::ostream& operator<<(std::ostream&, const std::string&);
So the following sample will work:
#include <iostream>
#include <string>
int main()
{
std::string message = "Hello World!\n";
operator<<(std::cout, message);
}
Concerning my original goal (to use for_each to print a vector of strings): It seems like it's better to use std::copy with std::ostream_iterator as illustrated here: How do I use for_each to output to cout?

You're looking for std::ostream& operator<<(std::ostream&, const std::string&);. It's a free function.

std::cout << message; would be equivalent to operator << (std::cout, message) not what you've written.
operator << has been defined as a free function and not as a member function
std::ostream& operator<<(std::ostream& out, const std::string& s) { ... }

Related

Any way to get split_regex to accept a const string as input?

Following code compilation implodes with deep template error stack if I try to make string input const, but I do not understand why it should be mutable.
From thinking about algorithm const should be fine, also I checked that the argument is not modified after function call.
#include <string>
#include <iostream>
#include <boost/algorithm/string_regex.hpp>
int main()
{
std::string str("helloABboostABworld");
static const boost::regex re("AB");
std::vector<boost::iterator_range<std::string::iterator> > results;
boost::split_regex(results, boost::make_iterator_range(str.begin(),
str.end()), re);
for (const auto& range: results){
std::cout << std::string(range.begin(), range.end()) << std::endl;
}
}
Any way to make this code work with const std::string str;?
As per the comment, if the std::string being searched is const then the iterator type used in the results must be the associated const_iterator type for the container being searched. Hence if the string being searched is...
const std::string str("helloABboostABworld");
Then the results container should be...
std::vector<boost::iterator_range<std::string::const_iterator>> results;
So the complete example becomes...
#include <string>
#include <iostream>
#include <boost/algorithm/string_regex.hpp>
int main()
{
const std::string str("helloABboostABworld");
static const boost::regex re("AB");
std::vector<boost::iterator_range<std::string::const_iterator>> results;
boost::split_regex(results, boost::make_iterator_range(str.begin(),
str.end()), re);
for (const auto& range: results){
std::cout << std::string(range.begin(), range.end()) << std::endl;
}
}

How do I display the contents of a std::vector of my own datatype and display the name on the console using std::copy?

I would like to display the contents of the std::vector<User> using std::copy in a similar way to how I've achieved it through std::for_each in the code below.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
};
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
//How can I get std::copy to do what the std::for_each is doing?
std::copy(vectNames.begin(), vectNames.end(), std::ostream_iterator<User>(std::cout, "\n"));
//The following line is what I really would like std::copy to do.
std::for_each(vectNames.begin(), vectNames.end(), [](const User &user) {std::cout << user.GetName() << "\n"; });
}
You can simply overload the ostream operator:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
void print(std::ostream& where) const
{ where << m_sName; }
};
/// Overloaded ostream operator
std::ostream& operator<< (std::ostream& out, const User& user)
{
user.print(out);
return out;
}
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
std::copy(vectNames.begin(), vectNames.end(), std::ostream_iterator<User>(std::cout, "\n"));
}
In general I always have an overloaded ostream as part of classes that store and output information.
Because of your comment I am a new programmer and am experimenting with different ideas, I'm posting this answer as an alternative approach which also shows some algorithm that you might enthusiastic about.
I think that std::copy isn't the right tool if what you want to do is both
calling a member function on the objects in a collection, and only after that
copying/printing them to screen
One, and maybe the best, approach is the one in the atru's answer, which basically solves only point 2 with std::copy (and this is something you already knew how to do it, based on your question), and point 1 by overloading <<, which makes the trick.
The alternative I propose is based on the idea that "calling a member function on every object of a collection" is actually a transform operation of that collection. std::transform, however, just like std::copy acts on iterators, not on ranges, so they cannot be easily composed with one another.
Here comes Boost, with boost::copy and boost::adaptors::transformed which allow you to do this:
boost::copy(
vectNames | transformed([](auto const& x){ return x.GetName(); }),
std::ostream_iterator<std::string>(std::cout, "\n")
);
where vectNames is "piped into" transformed, which applies the lambda on every element of the collection, resulting in a new temporary collection, which is the argument to boost::copy. If you were to use std::copy, you would have to store the temporary somewhere, e.g. in temp, before passing to std::copy its iterators temp.begin() and temp.end().
The full example is below. I hope it will give you some insight in different, more functional, approaches.
#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
};
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
using boost::adaptors::transformed;
boost::copy(
vectNames | transformed([](auto const& x){ return x.GetName(); }),
std::ostream_iterator<std::string>(std::cout, "\n")
);
}

ostream in class does not have a type

Just got into C++ and I have a quick question.
After compiling with
g++ *.cpp -o output
I receive this error:
error: 'ostream' in 'class Dollar' does not name a type
These are my three files:
main.cpp
#include <iostream>
#include "Currency.h"
#include "Dollar.h"
using namespace std;
int main(void) {
Currency *cp = new Dollar;
// I want this to print "printed in Dollar in overloaded << operator"
cout << cp;
return 0;
}
Dollar.cpp
#include <iostream>
#include "Dollar.h"
using namespace std;
void Dollar::show() {
cout << "printed in Dollar";
}
ostream & operator << (ostream &out, const Dollar &d) {
out << "printed in Dollar in overloaded << operator";
}
Dollar.h
#include "Currency.h"
#ifndef DOLLAR_H
#define DOLLAR_H
class Dollar: public Currency {
public:
void show();
};
ostream & operator << (ostream &out, const Dollar &d);
#endif
Thank you for your time, and everything helps!
You have a number of errors in the code.
You heavily use using namespace std. This is a bad practice. In particular, this led to the error you faced: you don't have using namespace std in Dollar.h, thus the compiler has no idea what ostream means. Either put using namespace std in Dollar.h too, or better just stop using it and specify the std namespace directly, as in std::ostream.
You use std::ostream in your headers, but you don't include the corresponding standard library header <ostream> in them (<ostream> contains the definition of std::ostream class; for the full I/O library include <iostream>). A really good practice is to include all the dependencies of the header in the header itself, so that it is self-contained and can be safely included anywhere.
You are implementing a stream output operator with signature std::ostream & operator << (std::ostream &, Dollar const &), which is perfectly valid. However, you call it for a pointer to type Dollar. You should rather call it with the object itself, not the pointer, so you should dereference the pointer: std::cout << *cp;.
You implemented the output operator for the Dollar class, but use it for a variable of type Currency: this won't work. There is a way to do this - there do exist virtual methods for this exact reason. However, in this case the operator is a free function, thus it cannot be virtual. So, you should probably add a virtual print method to your Currency class, implement it in Dollar, and call it from output operator:
#include <iostream>
class Currency {
public:
virtual void print (std::ostream &) const = 0;
};
class Dollar : public Currency {
void print (std::ostream & out) const override {
out << "A dollar";
}
};
std::ostream & operator << (std::ostream & out, Currency const & c) {
c.print(out);
return out;
}
int main(/* void is redundant here */) {
Currency *cp = new Dollar;
std::cout << *cp;
// return 0 is redundant in main
}
You need to #include <iostream> within Dollar.h so that your std::ostream & operator is resolved by the compiler.

Print vector of vectors to ostream

Please consider the following code. I'm trying to output a vector of vectors to an ostream.
#include <iterator>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<T> &v) {
using namespace std;
copy(v.begin(), v.end(), ostream_iterator<T>(os, "\n"));
return os;
}
int main() {
using namespace std;
vector<string> v1;
cout << v1;
vector<vector<string> > v2;
cout << v2;
return 0;
}
The statement where I output a vector of strings works. The one where I output a vector of vectors of strings doesn't. I'm using g++ 4.7.0. I've tried w/ & w/o the -std=c++11 flag. In C++11 mode, it gives me this line in the half-page of errors.
error: cannot bind 'std::ostream_iterator<std::vector<std::basic_string<char> >, char, std::char_traits<char> >::ostream_type {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
I don't think I understand what it means. Could someone explain to me? I more or less know what an rvalue reference is, but I don't see why std::basic_ostream<char> wouldn't bind to std::basic_ostream<char>&&. Maybe I don't know it well enough. And is there a better way to do this?
Thanks in advance.
The error you're getting is a bit misleading. When I tried to compile your program I had to dig into the template vomit quite a bit, and I ended up with what I thought was going on:
error: no match for 'operator<<' in '*((std::ostream_iterator<std::vector<std::basic_string<char> >, char, std::char_traits<char> >*)this)->std::ostream_iterator<std::vector<std::basic_string<char> >, char, std::char_traits<char> >::_M_stream << __value'
Basically, when you called the copy algorithm, it used the output iterator, which used the << operator from within namespace std. Once there, lookup dictates that it try to find an overload for the template vector<> in the std namespace (because that's where IT resides).
So what you need to do is declare your stream operator for the vector template in namespace std. Surround your code with namespace std {} and see what happens...
It should be noted that what you're doing is basically modifying std::vector<> and adding behavior to it that wasn't there before. Doing this is non-standard, undefined, and can easily get in your way. You might consider other options.
I was wrong about this being a koenig lookup thing. It's not, the issue is name hiding similar to what occurs in classes here you declare an overload of something in a base (not an override).
The standard namespace declares several '<<' operators. These are basically functions named operator <<. In essence what you have is this:
void fun(int);
namespace Test {
void fun() { fun(3); }
}
int main() {
Test::fun();
}
Note that you can use fun(int) from the global namespace or any namespace that does not have any function named fun in it. You can't use it from the Test namespace.
This is why your use of operator << declared globally works fine from the global namespace but not from within the std namespace. The std namespace already has things named the same thing as the overload you're trying to provide and so that overload is hidden from all things within std. If you could put a using declaration there things would be different.
You need this utility library:
Pretty-print C++ STL containers
If you want to do this yourself (so as to teach yourself), then you need to define two overloads as:
For std::vector<T>:
template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<T> &v) {
using namespace std;
copy(v.begin(), v.end(), ostream_iterator<T>(os, "\n"));
return os;
}
For std::vector<std::vector<T>>:
template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<std::vector<T>> &v) {
using namespace std;
//NOTE: for some reason std::copy doesn't work here, so I use manual loop
//copy(v.begin(), v.end(), ostream_iterator<std::vector<T>>(os, "\n"));
for(size_t i = 0 ; i < v.size(); ++i)
os << v[i] << "\n";
return os;
}
If you have these overloads, then they together will handle these cases recursively:
std::vector<int> v;
std::vector<std::vector<int>> vv;
std::vector<std::vector<std::vector<int>>> vvv;
std::vector<std::vector<std::vector<std::vector<int>>>> vvvv;
std::cout << v << std::endl; //ok
std::cout << vv << std::endl; //ok
std::cout << vvv << std::endl; //ok
std::cout << vvvv << std::endl; //ok

Is there a C++ way to write file with any type of data?

Like this function in C:
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
I've looked in C++ file stream and found this one:
ostream& write ( const char* s , streamsize n );
this one only accepts char* instead of void*
but does it really matter if I use a C-style fwrite function in c++?
Streams are probably what you're looking for unless I misunderstand your question. There are many flavors that handle different jobs, like outputting to a file:
#include <cstdlib>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ofstream f("c:\\out.txt");
const char foo[] = "foo";
string bar = "bar";
int answer = 42;
f << foo << bar<< answer;
return 0;
}
...building strings like you would with printf:
#include <cstdlib>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
stringstream ss;
const char foo[] = "foo";
string bar = "bar";
int answer = 42;
ss << foo << bar<< answer;
string my_out = ss.str();
return 0;
}
...and they can even handle your own types, if you tell them how:
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
class MyGizmo
{
public:
string bar_;
int answer_;
MyGizmo() : bar_("my_bar"), answer_(43) {};
};
ostream& operator<<(ostream& os, const MyGizmo& g)
{
os << g.bar_ << " = " << g.answer_;
return os;
}
int main()
{
MyGizmo gizmo;
cout << gizmo;
return 0;
}
You can use either one. Using char * instead of void * doesn't make much real difference -- both fwrite and ostream::write are typically used for a variety of data types (with with C++, you need to add an explicit cast to char *, where in C the cast will happen implicitly, assuming you've included a proper prototype for fwrite).
In C++ you will want to use std::ofstream objects to write to a file. They can accept any type of data using the << operator, in much the same way that std::cout works for writing to the console. Of course, just like std::cout, if you want to print a custom type, you will need to define an operator<< overload for it.
An example:
std::ofstream outfile("myfile.txt");
int i = 5;
double d = 3.1415926535898;
std::string s = "Hello, World!";
outfile << i << std::endl;
outfile << d << std::endl;
outfile << s << std::endl;
To use std::ofstream, you need to #include <fstream>.
The outfile object will automatically close the file when it destructs, or you can call its close() method.
Contrary to already given answers, there is an important difference between fwrite() and ostream::write().
fwrite() writes binary data unmodified (well, on those poor non-Unix platforms there is endline translation, unless the file is opened in binary mode).
ostream::write() uses locale to transform every character, this is why it accepts char* rather than void*. Normally, it uses the default "C" locale, which does not do any transformation.
Just keep in mind that basic_ostream is a formatter on top of basic_streambuf, not a binary sink.