sending c-string to non-lvalue std::ostringstream weird behaviour - c++

Test code:
#include <iostream>
#include <sstream>
int main() {
std::ostringstream q;
std::cout << (dynamic_cast<std::ostringstream&>(q<<"hello"<<101).str()) << "\n";
std::cout << (dynamic_cast<std::ostringstream&>(std::ostringstream()<<"hello"<<101).str()) << "\n";
return 0;
}
Compiling with: g++ test.cpp
Output:
hello101
hello101
Compiling with: g++ -std=c++98 test.cpp
Output:
hello101
0x4b2ec0101
Looks like second string contains pointer to "hello" string intead of string itself. Why?
Is it some "feature" of c++98 standard or bug in gcc?

In C++03, the non-member operator<< (source) which is responsible for printing out C strings, namely
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
cannot accept an rvalue stream, so instead a member overload (inherited from the std::ostream base class) is chosen (source):
basic_ostream& operator<<( const void* value );
This prints out the address.
In C++11, there is an rvalue stream insertion operator,
template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
const T& value );
which ensures that the behaviour will be the same for lvalue and rvalue streams. Note that this overload could not have been written in C++03, as the only way to bind to an rvalue would be through a const lvalue reference.

Related

ostream: how are functions being called for this chained output?

Can anyone explain how the following iostream cout code is evaluated with each specific function including its declaration? Also, how the hex manipulator modifies the stream flags (my guess is it calls ios.flags()). For instance, I'm looking at ostream member functions and non member functions and am confused on what is being called and the order of evaluation (I think there is no specified order).
#include <iostream>
using namespace std;
int main()
{
int v = 0xFF;
cout << "0x" << hex << v << endl;
return 0;
}
std::hex and std::endl are standalone functions that take a std::ios_base& and std::basic_ostream& as input, respectively:
std::ios_base& hex( std::ios_base& str );
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
These functions manipulate the given stream as needed:
std::hex() calls the stream's setf() method to enable the std::ios_base::hex flag on it.
std::endl() writes a line break to the stream and then flushes the stream.
std::basic_ostream has non-static member operator<< overloads which take those kind of functions as input:
basic_ostream& operator<<(
std::ios_base& (*func)(std::ios_base&) );
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
These operator<< overloads simply call the given function with *this as input, and then return *this to the caller.
There is also a non-static member operator<< overload for taking an int as input:
basic_ostream& operator<<( int value );
This overload writes the int value to this, and then returns *this to the caller.
However, there is no non-static member operator<< overload for taking a string literal as input, but there are standalone non-member operator<< overloads for that:
template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
const CharT* s );
template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
const char* s );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
These overloads write the char* data to os, and then return os to the caller.
So, the expression:
cout << "0x" << hex << v << endl;
Ends up being evaluated like this:
operator<<(cout, "0x").operator<<(hex).operator<<(v).operator<<(endl);

How operator<< works with manipulator functions

In C++ is possible to write code like this:
cout << std::endl;
where, std::endl is a function that will be called with cout as a parameter. I'm wondering is it special feature of << and >> operators or there is a generic rule that allows to do same thing with other operators (for example with +)?
There is nothing really special about this. std::ostream::operator<< is simply overloaded to accept various types in input.
In the case of manipulator functions, operator<< is overloaded to accept certain types of function pointers as input by default:
basic_ostream& operator<<(
std::ios_base& (*func)(std::ios_base&) );
basic_ostream& operator<<(
std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
And then the implementations of those overloads just call whatever function is passed in to them, specifying *this as the function's input parameter, eg:
basic_ostream& basic_ostream::operator<<(std::ios_base& (*func)(std::ios_base&) )
{
(*func)(*this);
return *this;
}
basic_ostream& basic_ostream::operator<<(std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&))
{
(*func)(*this);
return *this;
}
basic_ostream& basic_ostream::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&))
{
(*func)(*this);
return *this;
}
Thus cout << std::endl; is simply calling cout.operator<<(std:endl);, where std::endl() matches the 3rd overload above:
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
In the case of the stream manipulator functions in the <iomanip> header, the manipulators that do not take any input parameters from user's code (ie std::boolalpha, std::showbase, etc) are usually implemented as standalone functions that match one of the overloads above, and thus DO get passed the ostream/istream directly as a parameter. However, the manipulators that take input parameters from user code (ie std::resetiosflags(), std::setbase(), etc) are defined to return "unspecified" (ie implementation-defined) types, where their implementations define additional overloads of operator<< and operator>> for those types so they can receive the ostream/istream to manipulate, respectively.
For example: std::fill might be implemented something like this:
template< class CharT >
struct fill_t { CharT ch; };
template< class CharT >
fill_t setfill( CharT c )
{
return fill_t<CharT>{c};
}
template< class CharT >
basic_ostream& operator<<(basic_ostream& out, const fill_t &in)
{
out.fill(in.ch);
return out;
}
Thus cout << setfill(' ') calls the equivalent of fill_t tmp = setfill(' '); operator<<(cout, tmp);
There is nothing special going on here. std::istream and std::ostream have overloads for the operator >> and operator << respectively in the form of
basic_istream& operator>>( std::ios_base& (*func)(std::ios_base&) );
basic_istream& operator>>( std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );
basic_istream& operator>>( basic_istream& (*func)(basic_istream&) );
basic_ostream& operator<<( std::ios_base& (*func)(std::ios_base&) );
basic_ostream& operator<<( std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );
basic_ostream& operator<<( std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
that allow the class to take a function pointer as the right hand side of the operator. When doing
cout << std::endl;
std::endl decays into a function pointer and the correct overload is called. You can do this with any operator for any type you have.
If you do plan to do this, think about the principal of least surprise, i.e don't use a common syntax that has a completely different meaning and use that as your custom overload.
You sure can.
#include <iostream>
struct Foo
{
int f = 0;
};
Foo operator+(Foo foo, int (*function)())
{
return {foo.f + function()};
}
int one()
{
return 1;
}
int main(int argc, const char* argv[])
{
Foo foo {10};
std::cout << (foo+one).f << std::endl;
}
Output:
11

Why does writing into temporary string stream object only print object addresses?

The following snippet is simplified version of a logger that I use. It extends std::ostringstream and can be filled using the <<-operator. Upon destruction all content is written to std::cout.
Writing (<<) directly into a temporary object, Logger(), I would expect it to print that input, however, it only prints the address of something on std::cout. When writing into a reference of a temporary object, Logger().stream(), works as expected.
Why is that happening?
Btw, this behavior only occurs in C++98-land (ideone), which I have to use. With C++11 (coliru) and C++14 (ideone) both call variants work as expected. What's different in C++11/14?
#include <iostream>
#include <sstream>
class Logger : public std::ostringstream
{
public:
~Logger()
{
std::cout << this->str() << std::endl;
}
Logger& stream()
{
return *this;
}
};
int main( int argc, char ** argv )
{
// 1.
// Prints an address, e.g. 0x106e89d5c.
Logger() << "foo";
// 2.
// Works as expected.
Logger().stream() << "foo";
// What is the difference between 1. and 2.?
return 0;
}
The operator<< that handles insertion of const char * is a non-member template:
template< class Traits >
basic_ostream<char,Traits>& operator<<(basic_ostream<char,Traits>& os, const char* s);
It takes its stream by non-const (lvalue) reference, which does not bind to temporaries.
In C++98/03, the best viable function is the member operator<<(const void *), which prints an address.
In C++11 and later, the library supplies a special operator<< for rvalue streams:
template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
const T& value );
which does os << value and returns os, essentially performing the output operation on an lvalue stream.
Relevant facts:
Logger() is an rvalue, but Logger().stream() is an lvalue.
The operator<< that takes a pointer and prints its address is a member of ostream&, whereas the operator<< that takes a const char* and prints the string is a free function,
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
const char* s);
Note that the first argument is a non-const lvalue reference, so it can't bind to an rvalue. Therefore, if the stream is an rvalue, this overload isn't viable. Consequently the const char* is converted to const void* and its address is printed. When you use Logger().stream(), which is an lvalue, this overload wins and the string is printed.
In C++11, a new rvalue stream insertion operator is added:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
with the effect os << x. Now this overload wins in Logger() << "foo", and forwards the argument as though the stream were an lvalue. Then the free function previously given is called.
C++11 added this overloaded of non-member operator<<:
template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
const T& value );
Now, the operator you think you're calling in the Logger() case is this one:
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
That works for the Logger().stream() case because that is an lvalue reference, but that doesn't work for Logger() << "foo" case. Logger() cannot bind to an lvalue reference. There, the only viable overload is the member operator<<:
basic_ostream& operator<<( const void* value );
which prints the address.

How to Generically Define Insertion Operators for all C++ IOStream Manipulators?

All,
Why does the following code fail to compile for 'std::endl', but it's fine for all of the other inserted types?
#include <sstream> // ostringstream
/// #brief A class that does streamed, formatted output via 'operator<<'.
class My_Stream
{
public:
/// #brief A member method that manipulates the underlying stream.
void foo()
{
m_oss << "foo_was_here; ";
}
private:
/// #brief The underlying stream.
std::ostringstream m_oss;
/// #brief 'operator<<' is a friend.
template< typename T >
friend My_Stream& operator<<( My_Stream& a_r_my_stream,
const T& a_r_value );
};
/// #brief A manipulator that calls a class method.
My_Stream& manipulator_foo( My_Stream& a_r_my_stream )
{
a_r_my_stream.foo();
return a_r_my_stream;
}
/// #brief The generic insertion operator.
template< typename T >
My_Stream& operator<<( My_Stream& a_r_my_stream,
const T& a_r_value )
{
a_r_my_stream.m_oss << a_r_value;
return a_r_my_stream;
}
/// #brief Define an iostream-like manipulator for my-stream.
typedef My_Stream& ( * my_stream_manipulator ) ( My_Stream& );
/// #brief The specialized 'my_stream_manipulator' insertion operator.
template<>
My_Stream& operator<<( My_Stream& a_r_my_stream,
const my_stream_manipulator& a_r_manipulator )
{
return a_r_manipulator( a_r_my_stream );
}
int main( int argc, char* argv[] )
{
My_Stream my_stream;
my_stream << 'c'; // char
my_stream << "string"; // c-string
my_stream << 1u; // unsigned int
my_stream << -1; // signed int
my_stream << 5.3f; // float
my_stream << -23.345; // double
my_stream << std::boolalpha; // std::ios_base manipulator
my_stream << std::endl; // std::ostream manipulator
my_stream << manipulator_foo; // my_stream manipulator
return 0;
}
I get the following G++ 4.5 error:
willo:~/test_cpp$ g++ -Wall test_overloaded_insertion_manipulators.cpp
test_overloaded_insertion_manipulators.cpp: In function ‘int main(int, char**)’:
test_overloaded_insertion_manipulators.cpp:60: error: no match for ‘operator<<’ in ‘my_stream << std::endl’
I expect the code to instantiate a 'operator<<' for std::endl, just like it did for the primitives, std::ios_base and my custom manipulator.
For context, I'm trying to create a light-API IOStream-like class that works with current IOStream manipulators, as well as one or two more custom manipulators.
Because endl is a function template:
template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
So the identifier itself is not a value. It only becomes a value (function pointer) when it's instantiated. But your operator<< is itself a template, and there is no type information available to the compiler to decide which types to instantiate endl with.
In contrast, e.g. boolalpha is:
ios_base& boolalpha(ios_base& str);
Hence why it works.
endl works for basic_ostream, because that one defines operator<< overloads as member functions taking function pointers; in particular:
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
So in a call like stream << endl, it would know charT and traits from type of this (i.e. left side of operator), and that would give it exact type of function pointer to expect on the right side - which it would then use to instantiate the corresponding version of endl. You can do the same for your class.
You need to define stream manipulators as a separate friend.
Add this friend:
// Note: Untested (don't have a compiler here).
template <class charT, class Traits>
friend My_Stream& operator<<( My_Stream&, std::basic_ostream<charT, Traits>& (*)(std::basic_ostream<charT, Traits>&));
Then you need to define the function:
template <class charT, class Traits>
My_Stream& operator<<( My_Stream& stream, std::basic_ostream<charT, Traits>& (*manip)(std::basic_ostream<charT, Traits>&))
{
(*manip)(stream.m_oss);
return stream;
}

Is possible to get automatic cast from user-defined type to std::string using cout?

As in the question, if I define a string operator in my class:
class Literal {
operator string const () {
return toStr ();
};
string toStr () const;
};
and then I use it:
Literal l1 ("fa-2bd2bc3e0");
cout << (string)l1 << " Declared" << endl;
with an explicit cast everything goes right, but if I remove the (string) the compiler says that it needs a cast operator declared in std::string. Shouldn't it cast my type automatically?
SOLVED: I'm overloading operator<< (ostream& os, const Literal& l).
No.. std::string would have to have a constructor that took Literal as an argument.
What you could do is overload operator << for your Literal class and have it cast and insert into the stream in there.
ostream &operator <<(std::ostream &stream, const Literal &rhs)
{
stream << (string) rhs;
return stream;
}
Short answer: Keep using a cast or toStr(), or write your own operator<< function. (I would prefer l1.toStr() to (string)l1.)
Long answer:
This might work if the Standard Library had a function
std::ostream& operator<<( std::ostream&, std::string const& );
Which it almost does, but not technically. Both ostream and string are really typedefs of template instantiations. And there's a template function for inserting one into the other.
// This is somewhat simplified. For the real definitions, see the Standard
// and/or your complying implementation's headers.
namespace std {
typedef basic_string<char> string;
typedef basic_ostream<char> ostream;
template <typename CharT>
basic_ostream<CharT>& operator<<(
basic_ostream<CharT>&,
basic_string<CharT> const&);
}
So when you use cout << str where the type of str is std::string, it can figure out to use that template function, with CharT = char.
But C++ doesn't allow you to have the compiler figure out both an implicit type conversion (Literal to string) and deduce template function template parameters (CharT = char) on the same call.