Given a class
class ostreamWrapper
{
private:
ostream * str;
public:
ostreamWrapper operator << (const char *);
}
where ostream * str will point to std::cout and ostreamWrapper operator << (const char *) sends the given text to the wrapped ostream str.
In this case, I can only instance << "const char * text" and no other printable data. Unlike directly <<ing a std::cout or std::cerr.
How can the operator method be implemented so it accepts any type of data just as std::cout or std::cerr directly do?
First, write a public operator<< template so it can accept any type and simply forward it to the wrapped ostream.
template <class T>
ostreamWrapper& operator<<(T&& x) {
*str << std::forward<T>(x);
return *this;
}
Second, in order to accept insertion of stream manipulator templates such as std::endl, add a second public operator<< that specifically accepts manipulators intended for the wrapped ostream:
ostreamWrapper& operator<<(ostream& (*manip)(ostream&)) {
*str << manip;
return *this;
}
Omitting the second overload will cause insertion of overloaded manipulators or manipulator templates to fail with "ambiguous overload" or similar error messages.
See an example of the proposed implementation, it would deduce the template parameter type and print accordingly, if you could use C++11 see #Brian answer:
#include <iostream>
using namespace std;
class ostreamWrapper {
private:
ostream* str;
public:
ostreamWrapper(ostream* str_v) : str(str_v) {}
template <typename T>
ostreamWrapper& operator<<(const T& t) {
if (str)
*str << t;
return *this;
}
};
int main() {
ostreamWrapper osw(&std::cout);
osw << 1 << " texto " << std::string(" otro texto ") << 1.2345;
return 0;
}
Related
I'm trying to implement a manipulator for my stream class. I don't know much about manipulators, but I think I'm doing everything right. The relevant parts of the code are below:
class stream
{
public:
stream& operator<<(bool b) { // send bool value and return *this; }
stream& operator<<(const char str[]) { // send string and return *this }
};
inline stream& endl(stream& s)
{
return s << "\r\n";
}
class stream stream;
int main()
{
stream << endl;
}
I don't know what I'm doing wrong, but instead of calling endl the compiler is calling stream::operator<<(bool). Any idea?
Seeing stream << endl; the compiler has to pick an overload from the operator <<s you provided. endl is not convertible to const char *, but it is convertible to bool, so that's what you get.
You probably meant to add an overload
stream& operator<<(stream &(*function)(stream &)) {
return function(*this);
}
inside of class stream that handles function pointers correctly.
Since your endl is neither a bool nor a const char[] (it is a free function), it is implicitly converted to a bool(true) and the following function is called:
stream::stream& operator<<(bool b)
You could define endl to be of a special type endl_t and define the right operator for it:
#include <iostream>
#include <string>
#include <array>
//Just make the operators `explicit`. See [this excellent answer on SO](http://stackoverflow.com/a/8239402/5470596).
class stream
{
public:
stream& operator<<(bool b) { std::cout << "bool\n" ; return *this; }
stream& operator<<(const char str[]) { std::cout << "const char[]\n" ; return *this; }
};
struct endl_t {} endl;
stream& operator<<(stream& s, endl_t)
{
s << "\r\n";
return s;
}
int main()
{
stream s;
s << endl; // prints "const char[]"
}
Live on coliru
In my project I use a class class called Message which inherits from std::ostringstream to print out human readable information of other class types.
So its << operator is overloaded several times taking my own class types which I want to print out.
class Message : public ostringstream
{
public:
Message() {};
virtual ~Message() {};
Message& operator <<(const MyTypeA &a) { return *this << a.getStr(); };
Message& operator <<(const MyTypeB &b) { return *this << b.identifier(); };
Message& operator <<(const MyTypeC &c) { return *this << c.foo(); };
// Pass everything unknown down to ostringstream, and always return a Message&
template<class T>
Message& operator <<(const T &t)
{
(std::ostringstream&)(*this) << t;
return *this;
}
};
Without the template
MyTypeA a,b;
Message m;
m << a << "-" << b;
the code would not compile, as (m << a << "-") would return a ostringstream& which would not be able to take 'b'. So I use the template to make sure to always return a Message&.
My Problem:
Message m;
m << "Hello, world" << std::endl;
generates a veeery long compiler error and I do not know why.
Here is a minimalistic "not" compilable example of my problem, and here is the corresponding compiler output.
Do not derive from any of the stream classes to create a new stream! The only reason to derive from std::ostream or std::istream is to create a stream properly set up to use a suitable stream buffer. Instead of deriving from a stream, you should derive from std::streambuf to create a new source or destination. To create output operators for new types you'd overload operator<<() with std::ostream& as first argument and your custom type as second argument. Likewise with std::istream&.
BTW, the problem you encountered is because std::endl is a function template. Trying to pass a function template somewhere requires that the appropriate instantiation can be deduced. Since your output operators don't cover a suitable signature, the instantiation of std::endl can't be deduced. I could state what's needed but that would be pointless as it is the wrong way to go anyway.
Here is how to make your code compile: http://pastebin.com/xAt5junf
The relevant excerpt:
class Message : public ostringstream
{
public:
Message() {};
virtual ~Message() {};
};
ostream& operator <<(ostream &os, const MyTypeA &a) {
return os << a.getStr();
};
ostream& operator <<(ostream &os, const MyTypeB &b) {
return os << b.getStr();
};
I am trying to understand how operator overloads works.
I want to code it so that I can write
Log(Log::LEVEL_ERR) << "fatal error: " << 13 ;
And for both the string and the number the overloaded operator is used.
I now have
class Log{
public:
std::ostream& operator<<(char const*);
}
std::ostream& Log::operator<<(char const* text){
if (Log::isToWrite()) {
printLevel();
std::cout << text;
}
return std::cout;
}
This only get's me the string but not the number, why?
Edit
#bitmask Just to be clear, you mean implement like this:
class Log{
public:
friend Log& operator<<(Log& in, char const* text);
}
friend Log& operator<<(Log& in, char const* text){
if (in.isToWrite()) {
in.printLevel();
std::cout << text;
}
return std::cout;
}
Because I get these everywhere now:
error: Semantic Issue: Invalid operands to binary expression ('Log' and 'const char [15]')
Maybe this is really simple but can you spell it out for me?
I'm really not getting it.
Because you returned an ostream&, the next << operator matches operator<<(ostream&, int). You should return *this; (type is Log&) instead, so that the next << operator matches an operator defined for your class.
I've been working on this school assignment. The assignment told us to make an object which had it's output operator ( << ) overloaded.
Here's my code:
#include <ostream>
using namespace std;
template <class T>
class CustomObject {
string print() {
string text = "";
for (int i = 0; i < num_items(); i++) {
text += queue[i];
text += " | \n";
}
return text;
}
friend std::ostream& operator <<(std::ostream &output, CustomObject &q) {
output << "" << q.print();
return output;
}
}
So I instantiate this object like this:
CustomObject<int> co();
and call its output method:
std::cout << co();
Which would inevitably call the print method, and return the string to the default output stream.
But, there's no visible output in my console/debugger.
What am I missing here?
PS this is not the complete class, it's generic because of several other methods and functionality that is not necessary to be shown here.
PPS the num_items() and queue variables are part of said rest, this class is a PriorityQueue object. So, queue is an array of the specified type (hence the generic declaration) and num_items() just returns the count of the array.
CustomObject<int> co();
That's a function declaration. Leave out the parenthesis.
std::cout << co();
Why are you appling operator() to co? Again, leave out the parenthesis. This should work:
CustomObject<int> co;
std::cout << co;
Alas, building and returning a string from a print method is hardly idiomatic C++. Here is what I would do:
template <typename T>
class CustomObject
{
// ...
public:
void print(std::ostream& os) const
{
for (int i = 0; i != num_items(); ++i)
{
os << queue[i] << " | \n";
}
}
};
std::ostream& operator<<(std::ostream& os, const CustomObject& object)
{
object.print(os);
return os;
}
If you want to be able to print temporary objects a well, you should make the parameter a const reference:
CustomObject const& q)
The following won't compile for me. I'm out of ideas... Any help?
template<>
inline
std::ostream& operator<< <const std::map<std::string, std::string> > (std::ostream& stream, const std::map<std::string, std::string>& some_map)
{
return stream;
}
g++ gives me the following error:
error: expected initializer before '<' token
Edit: 1
Okay, since everyone is telling me to overload, let me give you an example that wouldn't make sense for overloading. What if I have this:
template <typename T>
inline
std::ostream& operator<<(std::ostream& stream, const T& something)
{
stream << something.toString();
return stream;
}
class Foo
{
public:
Foo(std::string s)
{
name = s;
}
std::string toString() const
{
return name;
}
private:
std::string name;
};
class Bar
{
public:
Bar(int i)
{
val = i;
}
std::string toString() const
{
std::ostringstream stream;
stream << val;
return stream.str();
}
private:
int val;
};
int main(int, char**)
{
Foo foo("hey");
Bar bar(2);
std::cout << foo << std::endl;
std::cout << bar << std::endl;
return 0;
}
Now this won't work either.
I just want to avoid having to overload operator<< over and over by using a template like above. This seems like it should be possible. I would like to know if it is, and if so, how?
In such a scenario, overloading for both Foo and Bar to do the same thing would be a waste, that is why I am trying to avoid it.
Edit: 2
Okay, it appears that I am being misunderstood. Here is another attempt to clarify:
template <typename T>
std::ostream& operator<<(ostream& stream, const T& t)
{
for(typename T::const_iterator i = t.begin(), end = t.end(); i != end; ++i)
{
stream << *i;
}
return stream;
}
int main(int, char**)
{
set<int> foo;
list<string> bar;
vector<double> baz;
cout << foo << " " bar << " " << baz << endl;
};
The above code won't work mind you. Complains about ambiguity. But it seems like the better solution for printing out containers. If I did it the with overloading, I would need to write a version of operator<< for each container/datatype combination, which would yield a ridiculous amount of code duplication.
This doesn't need to be a template function.
std::ostream & operator<<(std::ostream & stream, const std::map<std::string, std::string> & some_map)
{
return stream;
}
Edit:
In reference to my comment about writing Java in C++(and sorry if it sounded rude, I didn't intend to be smarmy). Tell me if this doesn't work better for you. Instead of writing a "toString" method in the first place, just overload the operator<< to begin with. The function is nearly identical. Then, you can write a non-member template toString function that will automatically work with all of your classes, like this:
#include <sstream>
#include <string>
template<typename T>
std::string toString(const T & val)
{
std::ostringstream ostr;
ostr << val;
return ostr.str();
}
Edit 2
Here's my alternative if you still insist on doing it your way. Make all of your classes with the toString method inherit from an abstract class with a virtual toString method, then write one operator<< to handle all of them.
class Stringifiable
{
public:
virtual std::string toString() const = 0;
};
std::ostream & operator<<(std::ostream & ostr, const Stringifiable& something)
{
return ostr << something.toString();
}
Now the compiler will choose your overload over templates.
You can use SFINAE to remove the template overload from consideration. Note that this has to be a part of the signature of the function. Thus you can use boost::enable_if:
template < typename T >
typename boost::enable_if< meta_function_to_check_for_concept<T>, std::ostream&>::type
operator << (std::ostream & out, T const& t)
{
...
}
If you don't do this then your template will attempt to match almost anything and will explode for every use of << that is not in line with the concept you're trying to match.
Your example is a bit contrived and might not lend itself to this answer, but there are situations in which it's warranted. This is how to do it.
In Crazy Eddie's answer, he mentions SFINAE. Now, C++11 has that built in. If all types derive from the same base class, this is made pretty simple. Here's a more complete example using C++11:
#include <type_traits>
#include <iostream>
#include <ostream>
class MyBaseType {};
class MyClass : MyBaseType {};
class MyOtherClass : MyBaseType {};
class SomeType {};
template <typename T>
typename std::enable_if<std::is_base_of<MyBaseType,T>::value,std::ostream&>::type
operator<<(std::ostream& out, const T& x)
{
out << 1;
}
int main()
{
MyBaseType x;
MyClass y;
MyOtherClass z;
SomeType i;
std::cout << x << y << z; // success!
std::cout << i; // compile-time failure!
}