Sign in to follow this  
daerid

Interesting GCC template issue

Recommended Posts

daerid    354
Okay, I'm trying to make a really, really basic debugging class. However, it's just not compiling with MinGW (GCC 3.2.3). Here's the code: Debug.h
#ifndef __DEBUG_H__
#define __DEBUG_H__

#include <iostream>

class CDebug
{
public:
	CDebug(std::ostream& ostrm) : out(ostrm) : enabled(false) {}

	void Enable(bool set) { this->enabled = set; }
	bool Enabled() { return this->enabled; }

	template<class T>
	CDebug& operator << (T item)
	{
		if(this->Enabled())
			out << item;
		return *this;
	}

private:
	std::ostream& out;
	bool enabled;
};

extern CDebug Debug;


#endif//__DEBUG_H__
Debug.cpp
#include "Debug.h"
CDebug Debug(std::clog);
main.cpp
#include <iostream>
#include "Debug.h"

int main(int argc,char* argv[])
{
	Debug.Enable(true);
	Debug << "This is a test" << std::endl;
	Debug.Enable(false);
	Debug << "This is another test" << std::endl;
	return 0;
}
This is what I get when I try to compile (using latest stable MinGW and MSYS):
$ g++ -o test.exe main.cpp -lstdc++
main.cpp: In function `int main(int, char**)':
main.cpp:30: no match for `CDebug& << <unknown type>' operator
main.cpp:32: no match for `CDebug& << <unknown type>' operator
main.cpp:34:2: warning: no newline at end of file
What exactly is wrong here?

Share this post


Link to post
Share on other sites
xg0blin    752
Don't you need to put

template <class T>
class CDebug
{

};

or am I mistaken? I dunno, it's been ages since I've used C++.

Share this post


Link to post
Share on other sites
SiCrane    11839
That error is probably gcc's way of telling you that it doesn't know what overload for std::endl you're trying to pass to your operator<<(). Adding a specific operator<<() overloard for (std::ostream &)(*)(std::ostream &) should disambiguate things. ex:

CDebug & operator<< (std::ostream & (*manip)(std::ostream &)) {
if (this->Enabled())
out << manip;
return *this;
}

Share this post


Link to post
Share on other sites
Baraclese    172
You're not really instantiating the template function with a parameter here.
In any case you want CDebug to be a stream itself so do it like this (copied from my code[inlove]):

template <typename charT, typename Traits=std::char_traits<charT> >
class basic_logfile : public std::basic_ofstream <charT, Traits>
{
public:

explicit basic_logfile(const char* filename)
{
this->open(filename);
this->flags(std::ios_base::unitbuf);
std::time_t t = std::time(NULL);
this->write(std::asctime(std::localtime(&t)), 24);
this->write("\n", 1);
}
~basic_logfile()
{
if (this->is_open())
this->close();
}
};
// instantiate for char type
typedef basic_logfile<char> logfile;


now you can simply make a global out of your logfile and you will be able to output any type to it which has the << operator defined.

Share this post


Link to post
Share on other sites
Pxtl    354
Anyone know a good online reference/tutorial on writing templates? Never done it myself, and now find that I have to (damn Python for spoiling me with "classes as arguments"). For example, is it possible to pass non-class arguments into template constructors?

Share this post


Link to post
Share on other sites
daerid    354
SiCrane:

Thanks, (std::ostream &)(*)(std::ostream &) is exactly what I needed. Trying to dig that out of the definition for std::endl was turning out to be a nightmare.

And I don't want the Debug to be an ostream, I want it to wrap an ostream so that I can control what goes to it, and so I can wrap whatever ostream I want (cout,cerr,clog, any ofstream, etc).

Share this post


Link to post
Share on other sites
risingdragon3    382
Since libgdn was brought back to my attention a while ago, you might have a look at the logging system in there. It pretty much wrapped it so that you coudl use an ostream to log out, and have multiple ostreams, as well as an ostream for the console window (ie you have a windowed window and a console output window as well). There was also some overriden stuff to let you pipe one ostream in and get two ostreams out..a splitter. Also there was an HTML output manip so you coudl get colors if you wanted.

And now...I'm done.

Damn, libgdn was actually kinda decent. heh.

Share this post


Link to post
Share on other sites
Doc    586
CDebug(std::ostream& ostrm) : out(ostrm) : enabled(false) {}


Is this even legal? I suspect not.

Share this post


Link to post
Share on other sites
DrPizza    160
How else would you initialize a reference member?

I wouldn't have a reference member myself (make it a pointer), but if that's what you're going to do, that's the only way to initialize it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this