I am working on a logging / tracing unit (and please don't point to existing ones, this is for the experience as much as for the result).
To get a run-time calling stack trace, the idea is to construct a TraceObject
instance first thing a function is entered, which carries the information of the current class and function. Somewhat akin to:
TraceObject to( "MyClass", "myClassFunction" );
The constructor of TraceObject
pushes this
on a per-thread stack, the destructor pops it again. The stack can thus be queried for the call stack.
I got this working to satisfaction. However, there is a small snitch: The object to
. It will, by design, never be referred to by that name. Hence, it does not need to have a name, least of all one that might collide with any identifiers used by the client (or, in case of _
prefix, the implementation).
tl;dr
Is it possible to create an anonymous, non-temporary object on the stack (i.e. one that will live until the function returns, but doesn't have an identifier), and if yes, how would it be done?
An anonymous object is essentially a value that has no name. Because they have no name, there's no way to refer to them beyond the point where they are created. Consequently, they have “expression scope”, meaning they are created, evaluated, and destroyed all within a single expression.
You create anonymous types by using the new operator together with an object initializer. For more information about object initializers, see Object and Collection Initializers. The following example shows an anonymous type that is initialized with two properties named Amount and Message .
It is not possible to create more than one anonymous object at a time. When constructor execution ends , destructor is executed to destroy the object.
Variables without names are called anonymous variables.
No.
There are anonymous objects in C++, temporaries that are the results of expressions, however they only live in the context of the statement they are in.
If you actually attempt to declare an anonymous object, you will confuse the parser and it'll think you are declaring... a function!
But then, is it necessary ?
If you accept to use macros to actually declare the TraceObject
, then it is as simple to use a macro for each trace; and thus provide the class and function there. Using __func__
or equivalent you can extract the class name and function name (bit of string parsing required, depends on the compiler) and work from there.
And of course, you would be using a macro for each trace anyway, because you would probably want the file name and line number!
As I say in my comment, scope limited anonymous variables cannot be used.
#define BEGIN_LOG TraceObject abcdefghij( "", __func__ );
void Function(){
BEGIN_LOG;
//bla bla
}
This should do it, provided there is a compiler macro to get Class name.
Edit: No Luck with a easy way to get class name, you might have to do something like what is suggested at Class name macro. Or just make do with __FILE__
.
Edit: You might want to try __func__
and __FUNCTION__
to see if either or both work as you want them to. Neither are C++ standard specified.
Some line number stuff:
#define XPASTE(arg1, arg2) PASTEX(arg1, arg2)
#define PASTEX(arg1, arg2) arg1 ## arg2
#define TRACELOG() \
TraceObject XPASTE(trace_object, __LINE__)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With