Macro and Template

J

jedi200581

Hello,

I have a singleton class that I'm using through macros:

//snippet
#define DO_SOMETHING ( myArgument) \
{ \
MyClass *myObject = MyClass::getInstance(); \
myObject->doSomething(myArgument); \
}; \

class MyClass
{
public:
MyClass() {}
static MyClass *getInstance ()
{
static MyClass *myObject = new MyClass();
return myObject;
}

void doSomething(MyArgument myArgument) { whatever(); }
};
// snippet

Now, I would like to template MyClass by another class, and don't
know how to do that! I guess I need some kind of initialization macro
where I give the template class to use, but how getInstance will
remember it for the DO_SOMETHING call ? Is there a way to store a
class in a variable or something ?

This code here:

//Snippet
#define DO_SOMETHING ( myArgument) \
{ \
MyClass<TemplateClass> *myObject =
MyClass<TemplateClass>::getInstance(); \
myObject->doSomething(myArgument); \
}; \

template <class T>
class MyClass
{
public:
MyClass() { _t = new T(); }
static MyClass *getInstance ()
{
static MyClass<T> *myObject = new MyClass<T>();
return myObject;
}

void doSomething(MyArgument myArgument) { _t->whatever(); }
T *_t;
};
// snippet

Obviously doesn't work, but can help you understand my pb. Is there
an elegant solution ?

Thank you.
 
A

Alf P. Steinbach

* (e-mail address removed):
I have a singleton class that I'm using through macros:

//snippet
#define DO_SOMETHING ( myArgument) \
{ \
MyClass *myObject = MyClass::getInstance(); \
myObject->doSomething(myArgument); \
}; \

Why are you using a macro?
 
J

jedi200581

* (e-mail address removed):





Why are you using a macro?

I designing a "logger". I have hundreds of source file, and I'm just
including an header file containg MyClass. Anywhere in my source file
I'm just addind: LOG("Warning : Db connection lost") and that's it, I
have my log. Using a macro is the simplest way to do that. I wan't to
template my logger so I can just output in a text form, or in XML, or
whatever ...
 
A

Alf P. Steinbach

* (e-mail address removed):
I designing a "logger". I have hundreds of source file, and I'm just
including an header file containg MyClass. Anywhere in my source file
I'm just addind: LOG("Warning : Db connection lost") and that's it, I
have my log. Using a macro is the simplest way to do that. I wan't to
template my logger so I can just output in a text form, or in XML, or
whatever ...

OK, in order to pick up logging call locations you need a macro.

However, you don't need that macro to know anything about the singleton:
just make it call a logging function that does the Real Stuff.

Now, what's this about "templating"? Can you give a short example of
the problem to be solved? Is it perhaps that you want the macro to
invoke different singletons (of different types) depending on something?
 
J

jedi200581

* (e-mail address removed):





OK, in order to pick up logging call locations you need a macro.

Exactly.

However, you don't need that macro to know anything about the singleton:
just make it call a logging function that does the Real Stuff.

Well, a simple function will not make the thing.
Now, what's this about "templating"? Can you give a short example of
the problem to be solved? Is it perhaps that you want the macro to
invoke different singletons (of different types) depending on something?

I want my logger to be extensible, so someone can write a back-end,
deriving from a abstract class that I define, and my logger, when
invoked from the macro, will use a standarized function in my backend
abstract class, which will output the log in different format.
Basically it's a line of text, but can be XML, JSON, or other text
format, eventually crypted or compressed format. This template thing
allow me to do that.
 
A

Alf P. Steinbach

* (e-mail address removed):
Well, a simple function will not make the thing.

Consider

#define LOG(s) makeLogEntry( whatever, whatever2, ... )

where only makeLogEntry() knows about the singleton.

I want my logger to be extensible, so someone can write a back-end,
deriving from a abstract class that I define, and my logger, when
invoked from the macro, will use a standarized function in my backend
abstract class, which will output the log in different format.
Basically it's a line of text, but can be XML, JSON, or other text
format, eventually crypted or compressed format. This template thing
allow me to do that.

OK, assuming that the argument types for LOG do not depend on type of
the active logger object, then that's not a template, that's an
installable object or function pointer. With polymorphism (virtual
functions), not templating. For example, you can use the same scheme as
with e.g. std::set_new_handler (client code is responsible for
installing the logger), or you can require client code to provide a
function that creates the singleton object and returns a pointer to it
(your code is responsible for installing the logger), or whatever.
 
N

naoki

* (e-mail address removed):







Consider

#define LOG(s) makeLogEntry( whatever, whatever2, ... )

where only makeLogEntry() knows about the singleton.



OK, assuming that the argument types for LOG do not depend on type of
the active logger object, then that's not a template, that's an
installable object or function pointer. With polymorphism (virtual
functions), not templating. For example, you can use the same scheme as
with e.g. std::set_new_handler (client code is responsible for
installing the logger), or you can require client code to provide a
function that creates the singleton object and returns a pointer to it
(your code is responsible for installing the logger), or whatever.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?- Hide quoted text -

- Show quoted text -

Would it be a bad Idea to use streams-like scheme (<< operator) ?
For example:
MyLogStream logger; // <-- declared somewhere in the program...

logger << "This is a log line, value=" << value << endl;

a user defined type could use the scheme by defining a friend function
like is done with std::eek:stream:

// snippet
class UserDefinedClass {
friend MyLogStream& operator<<(MyLogStream& ls, const
UserDefinedClass& udc) {
// insert data to log stream
ls << udc.data;
.
.
.
return ls;
}
.
.
.
}
// snippet
 
J

jedi200581

Would it be a bad Idea to use streams-like scheme (<< operator) ?
For example:
MyLogStream logger; // <-- declared somewhere in the program...

logger << "This is a log line, value=" << value << endl;

a user defined type could use the scheme by defining a friend function
like is done with std::eek:stream:

// snippet
class UserDefinedClass {
friend MyLogStream& operator<<(MyLogStream& ls, const
UserDefinedClass& udc) {
// insert data to log stream
ls << udc.data;
.
.
.
return ls;
}
.
.
.}

// snippet

Thanks for your answer!
I'm not happy with this solution, first because I need this log
library to be simple... no, not simple, simplistic! There is hundreds
of source files and lots of developers, and I want my macros to handle
the job of allocating the logger. Moreover, it allows me to track the
logs (source filename and line number using __FILE__ and __LINE__).
Then, using a function as a friend requires you to modify you logger
each time you are adding a back end, which is inelegant IMHO.
 
J

jedi200581

OK, assuming that the argument types for LOG do not depend on type of
the active logger object, then that's not a template, that's an
installable object or function pointer. With polymorphism (virtual
functions), not templating. For example, you can use the same scheme as
with e.g. std::set_new_handler (client code is responsible for
installing the logger), or you can require client code to provide a
function that creates the singleton object and returns a pointer to it
(your code is responsible for installing the logger), or whatever.

Ok so if I get you right, if the user want a logger that outputs in
XML, he just create its own class derived from MyClass, like:

// snippet
class MyClassXML : public MyClass
{
virtual void doDomething(MyArgument myArgument) { whateverXML(); }
};
// snippet

So my macros now would be like:

// snippet
MyClass *g_myObject = NULL;

#define DO_SOMETHING_FIRST( myArgument, myObject ) \
{ \
assert(g_myObject == NULL);
g_myObject = myObject;
DO_SOMETHING( myArgument ); \
}

#define DO_SOMETHING ( myArgument ) \
{ \
g_myObject->doSomething( myArgument ); \
}
// snippet

So this still means that the logger allocation would have to be
handled by the client (client = user) and it's something I'm trying to
avoid. This getInstance thing is something I don't want to loose.
Moreover here, there is a risk to call DO_SOMETHING_FIRST more than
once, then a risk of asserting or leaking memory depending on what you
do in that case... So I can pass a function pointer to the client-
defined getInstance function. Still, I got to perform an
initialization, and now the client to provide this getInstance
function.

Your solutions are great, but I'm sure my macro/template thing can be
solved by some wonderful elegant c++ trick a la BOOST :)))
Still looking for this trick!
 
A

Alf P. Steinbach

* (e-mail address removed):
OK, assuming that the argument types for LOG do not depend on type of
the active logger object, then that's not a template, that's an
installable object or function pointer. With polymorphism (virtual
functions), not templating. For example, you can use the same scheme as
with e.g. std::set_new_handler (client code is responsible for
installing the logger), or you can require client code to provide a
function that creates the singleton object and returns a pointer to it
(your code is responsible for installing the logger), or whatever.
[snip]

Your solutions are great, but I'm sure my macro/template thing can be
solved by some wonderful elegant c++ trick a la BOOST :)))
Still looking for this trick!

The solutions I mentioned are not mine. Exactly what the perceived
problem is, is unclear. Perhaps just study existing implementations of
logging facilities (John Torjo proposed a logging facility for Boost, it
is available at <url: http://torjo.com/code/logging.zip>, but keep in
mind that it evidently didn't make it into Boost).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top