The function you've overloaded takes a left hand side of std::ostream&
and a right hand side of const std::string&
. This is how you called the function:
fl << "!!!Hello World!!!" << endl;
The left hand side matches perfectly, but the right hand side doesn't. The string you've passed is not an std::string
but rather a object of type char const*
. The custom overload you made isn't called even though there is a viable conversion from char const*
to const std::string&
because there is in fact a perfect match elsewhere.
The overload that is a perfect match is the overload found in namespace std
which is signed as:
namespace std { // Simplification:
std::ostream& operator<<(std::ostream& os, char const* str);
}
This is a better match because no conversion needs to be made on the matter of the right hand parameter. Another reason this works is because of something called ADL or Argument Dependent Lookup. Normally you would have to explicitly qualify names or functions from other namespaces (like std
) from outside of those namespaces, but when it comes to ADL, if the compiler can find a function which takes a class of user-defined type from that same namespace, calling said function will not require explicit qualification from outside that namespace. Therefore the above is equivalent to:
std::operator<<(f1, "!!!Hello World!!!") << std::endl;
You can see this while using std::getline()
. The following is well-formed even though we do not use using namespace std
or using std::getline
:
getline(std::cin, line);
Because std::cin
is within the same namespace as the function std::getline()
, you do not need to append std::
to the function call.
So for your overload to be called, there has to be a better match. You can force this by creating a std::string
explicitly:
fl << std::string("!!!Hello World!!!") << endl;
Your overload is called and not the one in namespace std
because overloads in the enclosing namespace are considered before outer ones like std
. But not only is this non-intuitive, it will also cause other issues.
Your function needs to return the type std::ostream&
instead of void
and have a return os
statement so that you can chain the << endl
expression.
Inside your function you're performing infinite recursion on the os << str
line. There are a number of ways to solve this issue, the easiest being to do os << str.c_str()
so that the char const*
overload in namespace std
gets called.
Your method isn't the best way to do this so for more complete and better solutions, look toward the other answers and comments in this thread.
ostream
with astreambuffer
that transparently multiplexes to any number of other streams. There is no standard one. – Engedi