user4546925
user4546925

Reputation:

How to implement C++ stream manipulator endl correctly?

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?

Upvotes: 1

Views: 888

Answers (2)

YSC
YSC

Reputation: 40070

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

Upvotes: 2

nwp
nwp

Reputation: 9991

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.

Upvotes: 5

Related Questions