overloading of the insertion(<<)-operator

Huhu...

I am writing a Logger and for this i want to overload the operator<<() to Log strings and numbers...

I encounter problems which make me want to ask the following:

If I want to do: logger << string e.g.: log << "lalelu";
do i have to overload the << for std::string,too? or is it sufficient to do the following:

1
2
3
4
5
class Logger
{
//...
Logger& operator<<(std::string) {/*do stuff*/  return this;};
};


i am asking, because i get the following error(s): c2678
binary 'operator' : no operator defined which takes a left-hand operand of type 'type' (or there is no acceptable conversion)
& c2784
error C2784: "std::basic_ostream<_Elem,_Traits> &std::operator <<(std::basic_ostream<_Elem,_Traits> &,_Elem)": template-Argument für "std::basic_ostream<_Elem,_Traits> &"can not be deduced from 'Logger'
Last edited on
What kind of a Logger is this?
I would do a ostream as logger. (derive from std::streambuf or somewhat)

Why bother with rewriting this again, if ostream provides these abilities?

Do you need an example, how to do an ostream?

BTW: try,

friend Logger & operator<< (Logger &, const string &);
Last edited on
I already did try this with an friend function but that didnt work, too...

I format the text within the operator functions body and then send it to two other functions which output it in two different ways...

or do you mean that i should derieve from ostream?... <- edit: that´s not an option
Last edited on
Here some "pseudo code"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <streambuf>
#include <iostream>
#include <cstdio>

class LogBuf : public std::streambuf {
protected:
    virtual 
    int_type overflow(int_type c) {
        if (c == EOF)
            return EOF;
        int rv1 = write_char_func1(ch);
        int rv2 = write_char_func2(ch);
        // your error checking
        if (rv1 == ERROR || rv2 == ERROR)
            return EOF;
        return 1;
    }
    
    // this is optional, but due to performance i recommend to write this too
    virtual 
    std::streamsize xsputn(const char *buf, std::streamsize num) {
        int rv1 = write_cstring_func1(buf, num); 
        int rv2 = write_cstring_func2(buf, num);
        // your error checking
        if (rv1 == ERROR || rv2 == ERROR)
            return EOF;
        // please make somehow sure to write num chars... ;-)
        // normally you would return how many chars could be written
        // same in overflow
        return num;
    }
};

class LogStream : public std::ostream {
private:
    LogBuf buf;
public:
    explicit LogStream() : std::ostream(buf) { }
};


EDIT:

doh, too late. didn't read your edit.
Last edited on
so this means i can´t do this if i am unwilling to derieve from ostream and if i cant write my own << operator for std::string?^^...
This does work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
using namespace std;

class Logger {
private:
    string name_;
public:
    Logger(string name) : name_(name) { }
    ~Logger() { }
    
    Logger &operator<< (string str)
    {
        cout << name_ << ": "<< str;
        return *this;
    }
};

int main()
{
    Logger log1("Logger1");
    Logger log2("Logger2");
    
    log1 << "Hallo Welt.\n";
    log2 << "Hallo Welt.\n";
}
Logger1: Hallo Welt.
Logger2: Hallo Welt.


So you just did not give enough informations. Do you have a template class?

Maikel


EDIT:
OOOHH i campared just now.. if you return Logger& by reference, then use *this and not this..
Last edited on
good old "hallo welt:P"...

im not sure what´s the difference between the preceding and mine^^... except from the *this instead of this, which i did miss...
If thats the case I can not recreate your error. And thus can not help you.
But you have the option to provide us with more code... ;-)

Maikel
1
2
3
4
5
6
7
8
9
10
class A
{
Logger *pL;
Logger* GetLogger() {return Logger};
};

class Logger
{
Logger& operator<<(string);
};

1
2
3
4
5
6
A a;
Logger log;
someothermethod()
{
(*a->GetLogger()) << "Hello World";
};


thats what i got... or something like it...
Last edited on
I still dont get your problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>

class Logger {
private:
    std::string name_;
public:
    Logger(std::string name) : name_(name) { }
    Logger& operator<<(std::string str);
};

Logger &Logger::operator<< (std::string str)
{
    std::clog << name_ << ": " << str;
    return *this;
}

class A {
private:
    Logger *log_;
public:
    A(std::string log_name) : log_(new Logger(log_name)) { }
    ~A() { delete log_; }    
    Logger *log() { return log_; }
};

int main()
{
    A a("Logger 1");
    *a.log() << "Hello World!\n";
}
here´s the responsible Part of the code:

the error appears in WinsockManager.cpp

I use vs2008

file Manager.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once

class Logger;
class WinsockManager;
class Manager
{
public:
	Manager(void);
	~Manager(void);

	Logger* GetLogger() {return m_Log;};
	WinsockManager* GetWinsockManager() {return m_WinsockManager;};

private:
	Logger* m_Log;
	WinsockManager* m_WinsockManager;;
};


file "Manager.cpp"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "Manager.h"
#include "WinsockManager.h"
#include "Logger.h"

Manager::Manager(void)
{
	m_Log = new Logger;
	m_WinsockManager = new WinsockManager(this);
}

Manager::~Manager(void)
{
	delete m_Log;
	delete m_WinsockManager;
}


file "WinsockManager.h"
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once
#include "Manager.h"

class WinsockManager
{
public:
	WinsockManager(Manager* pM) : m_pMM(pM) {};
	~WinsockManager(void);

	Manager* m_pMM;

	void DO();
};


file "WinsockManager.cpp"
1
2
3
4
5
6
7
8
9
10
#include "WinsockManager.h"

WinsockManager::~WinsockManager(void)
{
}

void WinsockManager::DO()
{
	*m_pMM->GetLogger() << "Hallo Welt!";      // <----- Error Goes Here
}


file "Logger.h"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include <string>
#include <iostream>
#include "Manager.h"

using namespace std;

class Logger
{
public:
	Logger(void);
	~Logger(void);

	Logger& operator<<(string);
};


file "Logger.cpp"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "Logger.h"

Logger::Logger(void)
{
}

Logger::~Logger(void)
{
}

Logger& Logger::operator <<(string str)
{
	cout << str.c_str();
	return *this;
}
Last edited on
The problem is just what the error is saying. In the scope of your DO function the << operator was not known. Just do an include "logger.h" in your winsockmanager.cpp.

Maikel
thank you very much... but now i get the following:

error LNK2019: reference to non resolved external symbol ""class CLogger __cdecl operator<<(class CLogger,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??6@YA?AVCLogger@@V0@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)" in Funktion ""private: unsigned short __thiscall CWinsockManager::BindSockets(void)" (?BindSockets@CWinsockManager@@AAEGXZ)". WinsockManager.obj
Last edited on
anyone may have a clue what is missing?...
I don't but I have an idea. Build a small project that compiles only the logger class and a small main function that attempts to log a few strings. Does that compile? You've only given us small pieces of code to look at so there is no way for me to figure out why you are getting a linker error. I cannot see how the project is being built. Also I have no idea if that is the only linker error that you get. Post something that I can compile and I'll try it or someone else will.
Topic archived. No new replies allowed.