operator<< cannot output std::endl -- Fix? - c++

The following code gives an error when it's supposed to output just std::endl:
#include <iostream>
#include <sstream>
struct MyStream {
std::ostream* out_;
MyStream(std::ostream* out) : out_(out) {}
std::ostream& operator<<(const std::string& s) {
(*out_) << s;
return *out_;
}
};
template<class OutputStream>
struct Foo {
OutputStream* out_;
Foo(OutputStream* out) : out_(out) {}
void test() {
(*out_) << "OK" << std::endl;
(*out_) << std::endl; // ERROR
}
};
int main(int argc, char** argv){
MyStream out(&std::cout);
Foo<MyStream> foo(&out);
foo.test();
return EXIT_SUCCESS;
}
The error is:
stream1.cpp:19: error: no match for 'operator<<' in '*((Foo<MyStream>*)this)->Foo<MyStream>::out_ << std::endl'
stream1.cpp:7: note: candidates are: std::ostream& MyStream::operator<<(const std::string&)
So it can output a string (see line above the error), but not just the std::endl, presumably because std::endl is not a string, but the operator<< definition asks for a string.
Templating the operator<< didn't help:
template<class T>
std::ostream& operator<<(const T& s) { ... }
How can I make the code work? Thanks!

You need to add this to your struct MyStream:
std::ostream& operator<<( std::ostream& (*f)(std::ostream&) )
{
return f(*out_);
}
std::endl is a function that appends a newline and flushes the underlying stream; this function signature accepts that function and applies it to the ostream member.
Then, as a test, defining foo::test as
void test() {
(*out_) << "start";
(*out_) << std::endl;
(*out_) << "done";
}
will correctly output
start
done

Related

How to write an insertion operator function template?

I'm trying to write a single function template instead of a bunch of similar overloads for the insertion operator. The redundant overloaded versions work, but when I try to unite them in a single function template, the compiler complains of ambiguity. For example:
#include <iostream>
#include <list>
class fooBar
{
public:
fooBar(int iVal): iValue(iVal) {}
int getValue() {return iValue;}
private:
int iValue;
};
class foo
{
public:
foo()
{
for(int i = 0; i < 64; i++)
lstFooBars.push_back(fooBar(i));
}
std::list<fooBar>& getList()
{
return lstFooBars;
}
private:
std::list<fooBar> lstFooBars;
};
class bar
{
public:
bar()
{
for(int i = 0; i < 64; i++)
lstFooBars.push_back(fooBar(i));
}
std::list<fooBar>& getList()
{
return lstFooBars;
}
private:
std::list<fooBar> lstFooBars;
};
std::ostream& operator<<(std::ostream& osOut, fooBar& fbrFooBar)
{
osOut << fbrFooBar.getValue();
return osOut;
}
template <typename T> std::ostream& operator<<(std::ostream& osOut, T& tContainer)
{
for(fooBar fbrFooBar: tContainer.getList())
osOut << "[" << fbrFooBar << "] ";
return osOut;
}
int main()
{
foo fooFoo;
bar barBar;
std::cout << std::endl << fooFoo << std::endl << std::endl;
std::cout << std::endl << barBar << std::endl << std::endl;
return 0;
}
...and the compiler tells me that:
test.cpp: In function ‘std::ostream& operator<<(std::ostream&, T&)’:
test.cpp:63:9: error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘const char [2]’)
63 | osOut << "[" << fbrFooBar << "] ";
| ~~~~~ ^~ ~~~
| | |
| | const char [2]
| std::ostream {aka std::basic_ostream<char>}
Why does it work when you overload the same function over and over for each case and it doesn't compile like this? What am I missing here?
You've inadvertedly added a possible overload for const char* by making this:
template<typename T>
std::ostream& operator<<(std::ostream& osOut, T& tContainer)
If you narrow it down a bit with SFINAE, it should work.
This overload will only work for types with a getList() member function for example:
template<typename T, typename U = decltype(std::declval<T>().getList())>
std::ostream& operator<<(std::ostream& osOut, T& tContainer)
operator<< by default takes chars as argument, not string literals (inside "s) https://www.cplusplus.com/reference/ostream/ostream/operator-free/.
So, in order to make the call in the code you provide not ambiguous, you should try either to use single chars, or std::string:
#include <iostream>
#include <list>
#include <string>
class fooBar
{
public:
fooBar(int iVal): iValue(iVal) {}
int getValue() {return iValue;}
private:
int iValue;
};
class foo
{
public:
foo()
{
for(int i = 0; i < 64; i++)
lstFooBars.push_back(fooBar(i));
}
std::list<fooBar>& getList()
{
return lstFooBars;
}
private:
std::list<fooBar> lstFooBars;
};
class bar
{
public:
bar()
{
for(int i = 0; i < 64; i++)
lstFooBars.push_back(fooBar(i));
}
std::list<fooBar>& getList()
{
return lstFooBars;
}
private:
std::list<fooBar> lstFooBars;
};
std::ostream& operator<<(std::ostream& osOut, fooBar& fbrFooBar)
{
osOut << fbrFooBar.getValue();
return osOut;
}
template <typename T> std::ostream& operator<<(std::ostream& osOut, T& tContainer)
{
for(fooBar fbrFooBar: tContainer.getList())
//osOut << std::string("[") << fbrFooBar << std::string("] "); // solution 1: use std::string
osOut << '[' << fbrFooBar << ']' << ' '; // solution 2: use single chars
return osOut;
}
int main()
{
foo fooFoo;
bar barBar;
std::cout << std::endl << fooFoo << std::endl << std::endl;
std::cout << std::endl << barBar << std::endl << std::endl;
return 0;
}

invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'ostream')

I'm trying to do
cout << Print(cout); However, there is an "invalid operands to binary expression ('ostream' (aka 'basic_ostream') and 'ostream')" error when compiling.
#include <iostream>
using namespace std;
ostream& Print(ostream& out) {
out << "Hello World!";
return out;
}
int main() {
cout << Print(cout);
return 0;
}
Why this doesn't work?
How can I fix this? Thanks!!
The syntax you might be looking for is std::cout << Print << " and hello again!\n";. The function pointer is treated as a manipulator. A built-in operator << takes the pointer to Print and calls it with cout.
#include <iostream>
using namespace std;
ostream& Print(ostream& out) {
out << "Hello World!";
return out;
}
int main() {
cout << Print << " and hello again!\n";
return 0;
}
Here is your second request:
#include <iostream>
#include <vector>
#include <iterator>
template <class Argument>
class manipulator
{
private:
typedef std::ostream& (*Function)(std::ostream&, Argument);
public:
manipulator(Function f, Argument _arg)
: callback(f), arg(_arg)
{ }
void do_op(std::ostream& str) const
{
callback(str, arg);
}
private:
Function callback;
Argument arg;
};
template <class T>
class do_print : public manipulator<const std::vector<T>&>
{
public:
do_print(const std::vector<T>& v)
: manipulator<const std::vector<T>&>(call, v) { }
private:
static std::ostream& call(std::ostream& os, const std::vector<T>& v)
{
os << "{ ";
std::copy(v.begin(), v.end(),
std::ostream_iterator<T>(std::cout, ", "));
return os << "}";
}
};
template <class Argument>
std::ostream& operator<<(std::ostream& os, const manipulator<Argument>& m)
{
if (!os.good())
return os;
m.do_op(os);
return os;
}
template<class T>
do_print<T> Print(const std::vector<T>& v)
{
return do_print<T>(v);
}
int main()
{
std::vector<int> v{1, 2, 3};
std::cout << Print(v);
}

How to write a function wrapper for cout that allows for expressive syntax?

I'd like to wrap std::cout for formatting, like so:
mycout([what type?] x, [optional args]) {
... // do some formatting on x first
std::cout << x;
}
and still be able to use expressive syntax like
mycout("test" << i << endl << somevar, indent)
instead of being forced to be more verbose like
mycout(std::stringstream("test") << i ...)
How can I implement this? What type to make x?
Edit: added consideration for optional arguments
How about this:
struct MyCout {};
extern MyCout myCout;
template <typename T>
MyCout& operator<< (MyCout &s, const T &x) {
//format x as you please
std::cout << x;
return s;
}
And put MyCout myCout; into any one .cpp file.
You can then use myCout like this:
myCout << "test" << x << std::endl;
And it will call the template operator<< which can do the formatting.
Of course, you can also provide overloads of the operator for special formatting of specific types if you want to.
EDIT
Apparently (thanks to #soon), for standard manipulators to work, a few more overloads are necessary:
MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ostream &)) {
f(std::cout);
return s;
}
MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios &)) {
f(std::cout);
return s;
}
MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios_base &)) {
f(std::cout);
return s;
}
EDIT 2
I may have misunderstoor your original requirements slightly. How about this (plus the same manipulator overloads as above):
struct MyCout
{
std::stringstream s;
template <typename T>
MyCout& operator << (const T &x) {
s << x;
return *this;
}
~MyCout() {
somehow_format(s);
std::cout << s.str();
}
};
int main() {
double y = 1.5;
MyCout() << "test" << y;
}
This comes easy with variadic template arguments:
template <class T>
void print(T t)
{
std::cout << t;
}
template <class T, class... Args>
void print(T t, Args... args)
{
std::cout << t << std::endl;
print(args...);
}
int main()
{
std::cout << std::boolalpha;
print(3, 's', true, false);
}
Output:
3
s
true
false
Live Demo
A variation from the answers:
#include <iostream>
using namespace std;
class MyCout
{
public:
MyCout& operator()(bool indent) {
if ( indent ) cout << '\t';
return *this;
}
template<class T>
MyCout& operator<<(T t) {
cout << t;
return *this;
}
MyCout& operator<<(ostream& (*f)(ostream& o)) {
cout << f;
return *this;
};
};
int main()
{
MyCout mycout;
int x = 10;
mycout(true)<< "test" << 2 << x << endl ;
}
You can use this kind of class:
#include <iostream>
using namespace std;
class CustomOut
{
public:
template<class T>
CustomOut& operator<<(const T& obj)
{
cout << " my-cout " << obj;
return *this;
}
};
int main()
{
CustomOut mycout;
mycout << "test" << 4 << "\n" << 3.4;
}
You'd need more code to use std::endl and other functors, so i've used here simple \n instead.

Why does writing to temporary stream fail?

Consider the following code:
#include <sstream>
#include <iostream>
class Foo : public std::stringstream {
public:
~Foo() { std::cout << str(); }
};
int main()
{
Foo foo;
foo << "Test1" << std::endl;
Foo() << "Test2" << std::endl;
return 0;
}
When I execute this, it gives me:
004177FC
Test1
I do not understand why the second example gives me gibberish. The temporary should live until the entire expression is evaluated, so why does it not behave the same as the first example?
I tested it.
I can guess that operator<< cannot bind a temporary to a non-const reference, so any externally defined operator<< functions will not work on the Foo temporary, but any class member ones will so if ostream or ostringstream has any internal operator<< members they will work.
Therefore it may be that the overload to a pointer is a member function whilst the special one for const char * is externally declared.
The non-temporary can bind to the non-const reference for the more specialist overload.
If you really need this you can workaround with a wrapper
class Foo :
{
mutable std::ostringstream oss;
public:
~Foo()
{
std::cout << oss.str();
}
template<typename T>
std::ostream&
operator<<( const T& t ) const
{
return oss << t;
}
};
Tested and works. The first operator<< will return you the underlying stream.
I tried this too but it coredumped:
class Foo : std::ostringstream
{
Foo & nonconstref;
public:
Foo() : nonconstref( *this ) {}
~Foo()
{
std::cout << str();
}
template<typename T>
std::ostream&
operator<<( const T& t ) const
{
return nonconstref << t;
}
};
This also works:
class Foo : public std::ostringstream
{
public:
Foo() {}
~Foo()
{
std::cout << str();
}
Foo& ncref()
{
return *this;
}
};
int main()
{
Foo foo;
foo << "Test1" << std::endl;
Foo().ncref() << "Test2" << std::endl;
}

VC6 and template error

I am overloading operator << to implement a stream like interface for a class:
template<typename T>
CAudit& operator << ( const T& data ) {
audittext << data;
return *this;
}
CAudit& operator << ( LPCSTR data ) {
audittext << data;
return *this;
}
The template version fails to compile with "fatal error C1001: INTERNAL COMPILER ERROR (compiler file 'msc1.cpp', line 1794)". Non-template functions all compile correctly.
Is this due to VC6s deficiencies when handling templates and is there a way around this?
Thanks,
Patrick
EDIT :
the full class is:
class CAudit
{
public:
/* TODO_DEBUG : doesn't build!
template<typename T>
CAudit& operator << ( const T& data ) {
audittext << data;
return *this;
}*/
~CAudit() { write(); }//If anything available to audit write it here
CAudit& operator << ( LPCSTR data ) {
audittext << data;
return *this;
}
//overload the << operator to allow function ptrs on rhs, allows "audit << data << CAudit::write;"
CAudit& operator << (CAudit & (*func)(CAudit &))
{
return func(*this);
}
void write() {
}
//write() is a manipulator type func, "audit << data << CAudit::write;" will call this function
static CAudit& write(CAudit& audit) {
audit.write();
return audit;
}
private:
std::stringstream audittext;
};
The problem occurs with the function overload of operator << which is used to allow write() to be used as a stream manipulator:
CAudit audit
audit << "Billy" << write;
That overload of the template for function pointers surely is too much for good old Visual Studio 6.
As a workaround you could define a type for your manipulator and overload operator<< for that type.
Here's some code:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <sstream>
#include <windows.h>
class CAudit {
std::ostringstream audittext;
void do_write() {}
public:
~CAudit() { do_write(); }
// types for manipulators
struct Twrite {};
// manipulators
static Twrite write;
// implementations of <<
template<typename T>
CAudit& operator << ( const T& data ) {
audittext << data;
return *this;
}
CAudit& operator << ( LPCSTR data ) {
audittext << data;
return *this;
}
CAudit& operator << ( Twrite& ) {
do_write();
return *this;
}
};
// static member initialization
CAudit::Twrite CAudit::write;
int main(int argc, char* argv[])
{
CAudit a;
int i = 123;
const char * s = "abc";
a << i << s << CAudit::write;
return 0;
}
The kind of error definitely looks like the kind of crashes caused by VC6's pre-previous-standard implementation of templates.
The best advice is of course to upgrade to either VC7.0, 7.1, 8.0, 9.0 or the beta of 10.
To compare that to Windows versions, it's still using Windows 98 when Me, 2000, XP, Vista and 7 are available.
Having said that, you can simplify the lookup a lot by a simple trick:
class CAudit {
template<typename T>
CAudit& operator<<(T const& t) {
this->print(t);
return *this;
}
private:
void print(int);
void print(LPCSTR);
void print(CAudit & (*func)(CAudit &));
template<typename T> print(T const&);
};
The hope here is that the first lookup of operator<< finds the single member template. The other operator<< candidates are non-members for other classes and built-ins. They should be unambiguously worse that this template. The second lookup inside your operator only needs to deal with CAudit members called print.
template<typename T>
CAudit& operator << (T data ) {
audittext << data;
return *this;
}
EDIT:
#include <iostream>
using namespace std;
class CAudit{
public:
CAudit(){}
template< typename T >
CAudit &operator<<(T arg);
CAudit &operator<<(char s);
};
template< typename T>
void oldLog(T arg){
cout << arg;
}
template< typename T >
CAudit &CAudit::operator<<(T arg){
oldLog( arg );
return *this;
}
CAudit &CAudit::operator<<(char arg){
oldLog( arg );
return *this;
}
int main(){
CAudit e;
e << "Hello";
e << 'T';
return 0;
}
The problem does not seem to be in the code snippet you posted. This program works fine:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <sstream>
#include <windows.h>
class CAudit {
std::ostringstream audittext;
public:
std::string getAuditText() const { return audittext.str(); }
template<typename T>
CAudit& operator << ( const T& data ) {
audittext << data;
return *this;
}
CAudit& operator << ( int data ) {
audittext << data;
return *this;
}
CAudit& operator << ( LPCSTR data ) {
audittext << data;
return *this;
}
};
int main(int argc, char* argv[])
{
CAudit a;
int i = 123;
const char * s = "abc";
a << i;
a << s;
std::cout << "audittext is: '" << a.getAuditText() << "'\n";
return 0;
}
Could you post some more code?