Bruno Alano
Bruno Alano

Reputation: 643

Overload on << like cout error

I'm trying to create a class like std::cout, however, with colored output. The idea is to call colorstream, but when I overload the operator << gives error.

Codes below:

main.cpp

#include <colorstream/colorstream.hpp>

int main ( int argc, char **argv )
{
cpk::colorstream test;
test << "Hello World";

return 0;
}

colorstream/colorstream.hpp

#include <string>

#ifndef CPK_COLORSTREAM_HPP
#define CPK_COLORSTREAM_HPP

namespace cpk
{
    class colorstream
    {
    public:
        colorstream ( ) { };
        colorstream operator<<( std::string n );
    };
}

#endif // #ifndef CPK_COLORSTREAM_HPP

colorstream/colorstream.cpp

#include <string>
#include <iostream>

/**
 * CPK Color Stream Header
 */
#include <colorstream/colorstream.hpp>

cpk::colorstream::colorstream operator<<( std::string n )
{
    std::cout << n << std::endl;
}

This is the first time I'm trying to overload operators in, so please help me and if I can explain my mistake.

Thank you, Bruno Alano

@edit The error:

CMakeFiles/cpk.dir/source/cpk.cpp.o: In function `main':
cpk.cpp:(.text+0x45): undefined reference to `cpk::colorstream::operator<<(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
make[2]: ** [cpk] Erro 1
make[1]: ** [CMakeFiles/cpk.dir/all] Erro 2
make: ** [all] Erro 2

Upvotes: 0

Views: 354

Answers (3)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153840

Well, the error is that you're definition of the operator is garbled. It should be

cpk::colorstream cpk::colorstream::operator<< (std::string n)

That said, I strong recommend not to pursue this approach further! To create custom streams you want to derive from std::streambuf and override the relevant operations there (e.g. overflow() and, possibly, xsputn() for output streams).

Actually, if you want to change color e.g. using ANSI Escape Codes you can just create suitable color manipulators and use them with an std::ostream:

#include <iostream>

namespace color
{
    std::ostream& red(std::ostream& out) {
        return out << "\x1b[31m";
    }
    std::ostream& reset(std::ostream& out) {
        return out << "\x1b[0m";
    }
}

int main()
{
    std::cout << "hello " << color::red << "world" << color::reset << "\n";
}

On non-UNIX platforms some other mechanism might be necessary, though...

Upvotes: 3

James Folk
James Folk

Reputation: 46

I need more information on what you are trying to accomplish and what are the errors that are coming up.

I made an assumption with the code provided below that you wanted to output the color to standard out. I feel that I am completely wrong with this assumption, however here is the code...

main.cpp

#include <colorstream/colorstream.hpp>

int main ( int argc, char **argv )
{
    cpk::colorstream test;
    test.SetColor("RED");
    std::cout << test << std::endl;

    return 0;
}

colorstream/colorstream.hpp should be:

#include <iostream>
#include <string>

#ifndef CPK_COLORSTREAM_HPP
#define CPK_COLORSTREAM_HPP

namespace cpk
{
    class colorstream
    {
    public:
        std::ostream& operator<< (std::ostream& stream, const cpk::colorstream& cs);
        void SetColor(const std::string &color){m_Color = color;}
    private:
        std::string m_Color;
    };
}

#endif // #ifndef CPK_COLORSTREAM_HPP

colorstream/colorstream.cpp should be:

#include <string>
#include <iostream>

/**
 * CPK Color Stream Header
 */
#include <colorstream/colorstream.hpp>

std::ostream& operator<<(std::ostream& stream, const cpk::colorstream& cs) 
{
    stream << cs.m_Color; 
    return stream;
}

Upvotes: 0

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234514

When defining a member operator, what you need to qualify with the class name is the operator name, not the return type.

namespace cpk {
    colorstream colorstream::operator<<( std::string n )
    {
        std::cout << n << std::endl;
    }
}

Now, to allow chaining calls to << like you can do with std::cout you need to actually return a value from your operator!

namespace cpk {
    colorstream colorstream::operator<<( std::string n )
    {
        std::cout << n << std::endl;
        return *this;
    }
}

However, this will return a copy of the stream because it returns by value. That's probably not desirable, so you might be better with returning by reference:

    colorstream& colorstream::operator<<( std::string n )
    {
        std::cout << n << std::endl;
        return *this;
    }

Upvotes: 2

Related Questions