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);
}
Related
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;
}
I have template code which needs to convert some template type to string. For this I overload to_string for my own types. But the type can also be a string already. Then compilation fails, because there is no overload of to_string for type string itself (just returning its argument).
edit:
example code:
template<class T>
class TemplatedClass
{
public:
string toString() const
{
// this should work for both simple types like int, double, ...
// and for my own classes which have a to_string overload
// and also for string, which is the reason for my question
return string("TemplatedClass: ").append(to_string(t_));
}
private:
T t_;
};
You can just write your own templated function with proper overloads as follows:
#include <iostream>
#include <string>
using namespace std;
template<typename T>
std::string toString(const T& t) {
return std::to_string(t);
}
std::string toString(const char* t) {
return t;
}
std::string toString(const std::string& t) {
return t;
}
int main() {
cout << toString(10) << endl;
cout << toString(1.5) << endl;
cout << toString("char*") << endl;
cout << toString(std::string("string")) << endl;
return 0;
}
You can just combine all std::to_string and all your to_string by using derective. And pass std::string by value to minimize number of copies:
#include <string>
#include <iostream>
namespace convert {
std::string to_string(std::string s)
{
return s;
}
template<class T>
std::string stringify(T&& t)
{
using convert::to_string;
using std::to_string;
return to_string(std::forward<T>(t));
}
}
class Foo
{
public:
operator std::string () const { return "Foo"; }
};
namespace bar {
class Bar
{};
std::string to_string(const Bar&) {
return "Bar";
}
}
int main()
{
std::string s{"I'm lvalue string"};
std::cout << convert::stringify(42) << "\n";
std::cout << convert::stringify(std::string("I'm string")) << "\n";
std::cout << convert::stringify("I'm c-string") << "\n";
std::cout << convert::stringify(s) << "\n";
std::cout << convert::stringify(Foo{}) << "\n";
std::cout << convert::stringify(bar::Bar{}) << "\n";
return 0;
}
Note that with my approach you don't need an overload for const char * or any other type that is convertible to a string. Also this approach allows a user to add to_string overload for any class (it will be found by argument-dependent lookup).
For further optimization convert::to_string accepting a string by value can be split into lvalue and rvalue overloads.
Since C++17 you can use constexpr in if statements.
You can use it as follows:
#include <iostream>
#include <string>
template<typename Ty>
std::string ToString(const Ty& value) {
if constexpr (std::is_convertible_v<Ty, std::string>) {
return value;
}
else {
return std::to_string(value);
}
}
int main() {
std::cout << ToString(123) << std::endl;
std::cout << ToString(123.0) << std::endl;
std::cout << ToString("char*") << std::endl;
std::cout << ToString(std::string("std::string")) << std::endl;
return 0;
}
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.
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
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?