Is this even possible? I would like to write a macro that makes it easier to use some of my classes functionality.
Lets say I have 2 member functions in my class, setup() and cleanup(), where setup() sets up parameters for some operation that needs to be executed in its own scope, and cleanup() preforms cleanup (similar to a constructor and destructor concept).
Currently, I do this:
myClassInstance.setup(); //call the setup function
{ //start scope
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
myClassInstance.cleanup(); //cleanup
} //end scope, destroy locals
But would like to do something like this instead:
NEWSCOPE(myClassInstance) //calls setup()
{
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
} // calls cleanup() and destroys locals
My thought was to write a macro class that can be instantiated when the macro is used and setup() and cleanup() could be implemented in the constructor/destructor... or something like that...
Is this the right way to think about this or is there another way to write a macro that can essentially wrap around code written by the user?
* EDIT *
I fixed the naming convention as the function names were causing come confusion.
To create a new scope just use an anonymous block.
{
Obj obj;
/*
teh codez
*/
}//obj is deallocated
So you don't need a macro
It also sounds like you startScope and endScope should actually be constructor and destructor but once again it's hard to know without knowing what they actually do
UPDATE: I tried to give you an answer but instead I'll just rant.
similar to a constructor and destructor concept
To me that sounds like they are constructors and destructors, when you have the constructor and destructor doing the setup and cleanup the operations will be performed naturally and readably with RAII.
Another thing, you say your first solution (which I sort of accidentally gave back to you) is working, why workaround with a macro, in C macros were needed to simulate features (like templates, and objects) that C++ provides. For almost every situation, especially with C++11, macros will only make things worse and harder to debug, also in your case it seems like you actually have to type more when you do the macro?
My suggestion is rethink why you need to have a macro and why setup and cleanup can't be a constructor and destructor.
You might treat this in the same way as you would acquire a mutex lock with RAII. Something like this:
class MyClassScopeBlock
{
public:
MyClassScopeBlock( MyClass & c )
: obj(c)
{
obj.startScope();
}
~MyClassScopeBlock()
{
obj.endScope();
}
private:
MyClass & obj;
};
Then instantiate that as a local variable inside a scope block:
{
MyClassScopeBlock block( myClassInstance );
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
}
And if you really want, you can define a macro for it, to be used inside the scope block:
#define NEWSCOPE(inst) MyClassScopeBlock block(inst)
Personally, I prefer to stay away from macros whenever possible.
I spent hours trying to figure out how to make a Macro control a scope after seeing the BOOST_FOREACH Macro. In the process of figuring it out I ran across this question hoping it held the answer! But, not quite. So, I read through all of the code for the BOOST_FOREACH and the original design for BOOST_FOREACH. Then I felt kind of dumb... A Macro essentially inserts the code directly where it is placed. This means that we can have a Macro:
#define LOOP_3() \
for(int i = 0; i < 3; ++i)
Now, let us test it out!
LOOP_3() std::cout << "Hello World!" << std::endl;
/* === Output ===
Hello World!
Hello World!
Hello World!
*/
Yay! But, how is this useful? Well, at the end of the loop what happens to i?
The destructor is called which for i is not too fancy, but the idea is there.
All we need now is a class to handle this:
class SCOPE_CONTROL {
public:
SCOPE_CONTROL(): run(1) { std::cout << "Starting Scope!" << std::endl; }
~SCOPE_CONTROL() { std::cout << "Ending Scope!" << std::endl; }
bool run;
}
Let us put that sucker to use!
#define NEWSCOPE() \
for(SCOPE_CONTROL sc = SCOPE_CONTROL(); sc.run; sc.run = 0)
...
NEWSCOPE()
std::cout << " In the Body!" << std::endl;
std::cout << "Not in body..." << std::endl;
...
/* === Output ===
Starting Scope!
In the Body!
Ending Scope!
Not in body...
*/
To use the setup and cleanup functions, just change a small bit!
class SCOPE_CONTROL {
public:
SCOPE_CONTROL(MyClass myClassInstance): control(myClassInstance), run(1) {
control.setup();
}
~SCOPE_CONTROL() { control.cleanup(); }
bool run;
MyClass & control;
}
#define NEWSCOPE(control) \
for(SCOPE_CONTROL sc = SCOPE_CONTROL(control); sc.run; sc.run = 0)
...
NEWSCOPE(myClassInstance)
{
// CREATE LOCAL VARS
// DO STUFF IN THIS SCOPE
} // end scope, destroy locals
...
To make it even better use the ENCODED_TYPE (how to make in the design for BOOST_FOREACH very simple!) to allow SCOPE_CONTROL to be a template type.
A better alternative to putting the entire scope inside the macro replacement is to use something like a finally block. I've had success encapsulating the linked solution with these macros:
#define FINALLY_NAMED( NAME, ... ) auto && NAME = \
util::finally( [&]() noexcept { __VA_ARGS__ } );
#define FINALLY( ... ) CPLUS_FINALLY_NAMED( guard, __VA_ARGS__ )
#define DO_FINALLY static_cast< void >( guard );
usage:
{
myClassInstance.setup(); //call the setup function
FINALLY ( myClassInstance.cleanup(); ) //call the cleanup function before exit
// do something
DO_FINALLY // Explicitly note that cleanup happens here. (Only a note.)
}
This is exception-safe, and cleanup executes if and only if setup completes successfully, just like a constructor/destructor pair. But the the cleanup must not throw exceptions.
But if you want to do it the old-fashioned way…
You can contain the entire scope inside the macro by using variadic macros:
#define NEWSCOPE( INSTANCE, ... ) { \
(INSTANCE).setup(); /* call the setup function */ \
{ __VA_ARGS__ } /* paste teh codez here */ \
(INSTANCE).cleanup(); /* call the cleanup function */
I would recommend against putting cleanup inside the internal scope because the point of a scope is to contain declarations and names, but you want to use the name of INSTANCE from the outer scope.
usage:
NEWSCOPE ( myClassInstance,
// Do stuff.
// Multiple declarations, anything can go here as if inside braces.
// (But no #define directives. Down, boy.)
)
Related
In short: it is a smart pointers in C question. Reason: embedded programming and need to ensure that if complex algorithm is used, then proper deallocation occurs with little effort on the developer side.
My favorite feature of C++ is ability to execute a proper deallocation of object allocated on stack and that goes out of scope. GO language defer provides same functionality and it is a bit closer in spirit to C.
GO defer would be the desired way of doing things in C. Is there a practical way to add such functionality?
The goal of doing so is simplification of tracking when and where object goes out of scope. Here is a quick example:
struct MyDataType *data = malloc(sizeof(struct MyDataType));
defer(data, deallocator);
if (condition) {
// dallocator(data) is called automatically
return;
}
// do something
if (irrelevant) {
struct DT *localScope = malloc(...);
defer(localScope, deallocator);
// deallocator(localScope) is called when we exit this scope
}
struct OtherType *data2 = malloc(...);
defer(data2, deallocator);
if (someOtherCondition) {
// dallocator(data) and deallocator(data2) are called in the order added
return;
}
In other languages I could create an anonymous function inside the code block, assign it to the variable and execute manually in front of every return. This would be at least a partial solution. In GO language defer functions can be chained. Manual chaining with anonymous functions in C is error prone and impractical.
Thank you
In C++, I've seen "stack based classes" that follow the RAII pattern. You could make a general purpose Defer class (or struct) that can take any arbitrary function or lambda.
For example:
#include <cstddef>
#include <functional>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::function;
using std::string;
struct Defer {
function<void()> action;
Defer(function<void()> doLater) : action{doLater} {}
~Defer() {
action();
}
};
void Subroutine(int i) {
Defer defer1([]() { cout << "Phase 1 done." << endl; });
if (i == 1) return;
char const* p = new char[100];
Defer defer2([p]() { delete[] p; cout << "Phase 2 done, and p deallocated." << endl; });
if (i == 2) return;
string s = "something";
Defer defer3([&s]() { s = ""; cout << "Phase 3 done, and s set to empty string." << endl; });
}
int main() {
cout << "Call Subroutine(1)." << endl;
Subroutine(1);
cout << "Call Subroutine(2)." << endl;
Subroutine(2);
cout << "Call Subroutine(3)." << endl;
Subroutine(3);
return EXIT_SUCCESS;
}
Many different answers, but a few interesting details was not said.
Of course destructors of C++ are very strong and should be used very often. Sometime some smart pointers could help you. But the mechanism, that is the most resemble to defer is ON_BLOCK_EXIT/ON_BLOCK_EXIT_OBJ (see http://http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 ). Do not forgot to read about ByRef.
One big difference between C++ and go is when deffered is called. In C++ when your program leaving scope, where is was created. But in go when your program leaving function. That means, this code won't work at all:
for i:=0; i < 10; i++ {
mutex.Lock()
defer mutex.Unlock()
/* do something under the mutex */
}
Of course C does not pretends that is object oriented and therefore there are no destructors at all. It help a lot of readability of code, because you know that your program at line X do only what is written in that line. In contrast of C++ where each closing curly bracket could cause calling of dozens destructors.
In C you can use hated statement goto. Don't use it for anything else, but it is practical to have cleanup label at the end of function call goto cleanup from many places. Bit more complicated is when more than one resource you want do release, than you need more that one cleanup. Than your function finish with
cleanup_file:
fclose(f);
cleanup_mutex:
pthread_mutex_unlock(mutex);
return ret;
}
C does not have destructors (unless you think of the GCC specific variable attribute cleanup, which is weird and rarely used; notice also that the GCC function attribute destructor is not what other languages, C++ notably, call destructor). C++ have them. And C & C++ are very different languages.
In C++11, you might define your class, having a std::vector or std::function-s, initialized using a std::initialized_list of lambda expressions (and perhaps dynamically augmented by some push_back). Then its destructor could mimic Go's defer-ed statements. But this is not idiomatic.
Go have defer statements and they are idiomatic in Go.
I recommend sticking to the idioms of your programming languages.
(In other words: don't think in Go while coding in C++)
You could also embed some interpreter (e.g. Lua or Guile) in your application. You might also learn more about garbage collection techniques and concepts and use them in your software (in other words, design your application with its specific GC).
Reason: embedded programming and need to ensure that if complex algorithm is used, then proper deallocation occurs with little effort on the developer side.
You might use arena-based allocation techniques, and de-allocate the arena when suitable... When you think about that, it is similar to copying GC techniques.
Maybe you dream of some homoiconic language with a powerful macro system suitable for meta-programming. Then look into Common Lisp.
I just implemented a very simple thing like defer in golang several days ago.
The only one behaviour different from golang is my defer will not be executed when you throw an exception but does not catch it at all. Another difference is this cannot accept a function with multiple arguments like in golang, but we can deal it with lambda capturing local variables.
The implementations are here.
class _Defer {
std::function<void()> __callback;
public:
_Defer(_Defer &&);
~_Defer();
template <typename T>
_Defer(T &&);
};
_Defer::_Defer(_Defer &&__that)
: __callback{std::forward<std::function<void()>>(__that.__callback)} {
}
template <typename T>
_Defer::_Defer(T &&__callback)
: __callback{
static_cast<std::function<void()>>(std::forward<T>(__callback))
} {
static_assert(std::is_convertible<T, std::function<void()>>::value,
"Cannot be convert to std::function<void()>.");
}
_Defer::~_Defer() {
this->__callback();
}
And then I defined some macros to make my defer like a keyword in C++ (just for fun)
#define __defer_concatenate(__lhs, __rhs) \
__lhs##__rhs
#define __defer_declarator(__id) \
if (0); /* You may forgot a `;' or deferred outside of a scope. */ \
_Defer __defer_concatenate(__defer, __id) =
#define defer \
__defer_declarator(__LINE__)
The if (0); is used to prevent defer a function out of a scope. And then we can use defer like in golang.
#include <iostream>
void foo() {
std::cout << "foo" << std::endl;
}
int main() {
defer []() {
std::cout << "bar" << std::endl;
};
defer foo;
}
This will print
foo
bar
to screen.
GO defer would be the desired way of doing things in C. Is there a practical way to add such functionality?
The goal of doing so is simplification of tracking when and where object goes out of scope.
C does not have any built-in mechanism for automatically invoking any kind of behavior at the end of an object's lifetime. The object itself ceases to exist, and any memory it occupied is available for re-use, but there is no associated hook for executing code.
For some kinds of objects, that is entirely satisfactory by itself -- those whose values do not refer to other objects with allocated storage duration that need to be cleaned up as well. In particular, if struct MyDataType in your example is such a type, then you get automatic cleanup for free by declaring instances as automatic variables instead of allocating them dynamically:
void foo(void) {
// not a pointer:
struct MyDataType data /* = initializer */;
// ...
/* The memory (directly) reserved for 'data' is released */
}
For objects that require attention at the end of their lifetime, it is generally a matter of code style and convention to ensure that you know when to clean up. It helps, for example, to declare all of your variables at the top of the innermost block containing them, though C itself does not require this. It can also help to structure your code so that for each object that requires custom cleanup, all code paths that may execute during its lifetime converge at the end of that lifetime.
Myself, as a matter of personal best practices, I always try to write any cleanup code needed for a given object as soon as I write its declaration.
In other languages I could create an anonymous function inside the code block, assign it to the variable and execute manually in front of every return. This would be at least a partial solution. In GO language defer functions can be chained. Manual chaining with anonymous functions in C is error prone and impractical
C has neither anonymous functions nor nested ones. It often does make sense, however, to write (named) cleanup functions for data types that require cleanup. These are analogous to C++ destructors, but you must call them manually.
The bottom line is that many C++ paradigms such as smart pointers, and coding practices that depend on them, simply do not work in C. You need different approaches, and they exist, but converting a large body of existing C++ code to idiomatic C is a distinctly non-trivial undertaking.
For those using C, I’ve built a preprocessor in C (open source, Apache license) that inserts the deferred code at the end of each block:
https://sentido-labs.com/en/library/#cedro
GitHub: https://github.com/Sentido-Labs/cedro/
It includes a C utility that wraps the compiler (works out-of-the-box with GCC and clang, configurable) so you can use it as drop-in replacement for cc, called cedrocc, and if you decide to get rid of it, running cedro on a C source file will produce plain C. (see the examples in the manual)
The alternatives I know about are listed in the “Related work” part of the documentation:
Apart from the already mentioned «A defer mechanism for C», there are macros that use a for loop as for (allocation and initialization; condition; release) { actions } [a] or other techniques [b].
[a] “P99 Scope-bound resource management with for-statements” from the same author (2010), “Would it be possible to create a scoped_lock implementation in C?” (2016), ”C compatible scoped locks“ (2021), “Modern C and What We Can Learn From It - Luca Sas [ ACCU 2021 ] 00:17:18”, 2021
[b] “Would it be possible to create a scoped_lock implementation in C?” (2016), “libdefer: Go-style defer for C” (2016), “A Defer statement for C” (2020), “Go-like defer for C that works with most optimization flag combinations under GCC/Clang” (2021)
Compilers like GCC and clang have non-standard features to do this like the __cleanup__ variable attribute.
This implementation avoids dynamic allocation and most limitations of other implementations shown here
#include<type_traits>
#include<utility>
template<typename F>
struct deferred
{
std::decay_t<F> f;
template<typename G>
deferred(G&& g) : f{std::forward<G>(g)} {}
~deferred() { f(); }
};
template<typename G>
deferred(G&&) -> deferred<G>;
#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(x, y)
#define ANONYMOUS_VAR(x) CAT(x, __LINE__)
#define DEFER deferred ANONYMOUS_VAR(defer_variable) = [&]
And use it like
#include<iostream>
int main()
{
DEFER {
std::cout << "world!\n";
};
std::cout << "Hello ";
}
Now, whether to allow exceptions in DEFER is a design choice bordering on philosophy, and I'll leave it to Andrei to fill in the details.
Note all such deferring functionalities in C++ necessarily has to be bound to the scope at which it is declared, as opposed to Go's which binds to the function at which it is declared.
Think about this code in C/C++:
bool cond = true;
while(cond){
std::cout << "cond is currently true!";
}
Is it possible to create a function that can be called like this?
myFunction(some_parameters_here){
//Code to execute, maybe use it for callbacks
myOtherFunction();
anotherFunction();
}
I know you can use function pointers and lambda functions, but I was wondering if you can. I'm pretty sure there is a way to do so, because how would while() exist?
while(condition) { expression } is not a function but a control structure / a separate language construct; it executes expression again and again as long as condition evaluates to true (i.e. something != 0).
an function definition of the form void myFunction(int someParameter) { expression }, in contrast, is executed only when it is called by another function.
Hope it helps a bit;
Caution: this solution comes without the guarantee that your code reviewer will like it.
We can use a trick similar to the one Alexandrescu uses for his SCOPE_EXIT macro (awesome one-hour conference, this bit is at 18:00).
The gist of it: a clever macro and a dismembered lambda.
namespace myFunction_detail {
struct Header {
// Data from the construct's header
};
template <class F>
void operator * (Header &&header, F &&body) {
// Do something with the header and the body
}
}
#define myPrefix_myFunction(a, b, c) \
myFunction_detail::Header{a, b, c} * [&]
Using it as follows:
myPrefix_myFunction(foo, bar, baz) {
}; // Yes, we need the semicolon because the whole thing is a single statement :/
... reconstitutes a complete lambda after macro expansion, and lands into myFunction_detail::operator* with acess to foo, bar, baz, and the body of the construct.
I have a variable which is referenced a lot. It started out as an automatic variable.
Now I decided that in the middle of some code I want to call its dtor to reset its state, so I intend to deallocate and reallocate it. The standard way to do this of course is to call delete on it and make a new one.
Before:
void func() {
ClassName varname;
while (varname.check()/*...*/) { if (varname.function()/*...*/) { /* bunches of code ... */
/*... some more code ... */
}
}
}
Now I want:
void func() {
ClassName varname;
while (varname.check()/*...*/) { if (varname.function()/*...*/) { /* bunches of code ... */
if (key_code[SDLK_r]) { // Pressing R key should reset "varname"!
/* Here I want to dealloc and realloc varname! */
/* But if I declare varname as a ptr on line 2, */
/* line 3 (rest of code) must be refactored. */
}
}
}
}
My first attempt is to go change line 2 to be something like this
ClassName *varnamep = new ClassName();
ClassName& varname = *varnamep;
But I'm not sure if that means I'll be able to call delete on it later and reassign the reference!
delete &varname;
varnamep = new ClassName();
varname = *varnamep; // I assume compiler will error here because I can't reassign a ref.
Can I do this some other way? Or should I just suck it up and do a find-replace for turning varname. into varname->? In this particular case for my actual real situation I will probably implement a member function reset() and not worry about this actual problem. But I would like to know if there is some shortcut to being able to effectively treat references as pointers (or it could turn out that this is absurd nonsense)
Given ClassName varname, you could do this:
varname.~ClassName();
new (&varname) ClassName;
But I wouldn't recommend it. This uses two less-commonly-known features of C++: an explicit destructor call, and placement new. Only use this if it makes a significant difference in performance, as measured by your profiler, and the ClassName constructor can't throw an exception.
If ClassName::operator= does what you need (or you can modify it to do what you need), you can do this:
varname = ClassName();
That is more easily understood than using an explicit destructor call followed by placement-new.
Another common idiom:
varname.swap(ClassName());
This works if ClassName has an efficient swap method, like standard containers do. This is subtle enough that it probably deserves a comment if you decide to use it.
The standard way is not to delete and create a new instance. Just reassign the variable:
ClassName varname = .... ;
....
if (some condition) {
varname = SomethingElse;
}
and make sure that the copy constructor, assignment operator and destructor correctly deal with resources managed by ClassName.
Is is possible to register a function to be run immediately before main is entered? I know that all global objects are created before entering main, so I could put the code in the constructor of a global object, but that does not guarantee any particular order. What I would like to do is put some registration code into the constructor, but alas, I don't know what to put there :) I guess this is highly system-specific?
If you're using gcc, you can use the constructor attribute on a function to have it called before main (see the documentation for more details).
constructor
destructor
The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () has completed or exit () has been called. Functions with these attributes are useful for initializing data that will be used implicitly during the execution of the program.
Not sure this is exactly what you want... But it should do the job.
int main() {
static int foo = registerSomething();
}
It's better to explicitly calls such registration functions, either in main or on first access (but first access init could pose issues if you're multithreaded).
I am guessing here but:
You want to register something in a different compilation unit
You ran into a problem with the registration because the global variables in which you're saving registrations were not yet constructed.
C++ defines that a function-static is initialized sometime before it is first accessed, so you can work around it in the way shown below.
typedef std::map<std::string, std::string> RegistrationCache;
RegistrationCache& get_string_map()
{
static RegistrationCache cache;
return cache;
}
class Registration
{
Registration(std::string name, std::string value)
{
get_string_map()[name] = value;
}
};
Goal
Let's say you want the following:
STATIC_EXECUTE {
printf("This probably prints first"\n");
}
STATIC_EXECUTE {
printf("But order isn't guaranteed in the language spec, IIRC"\n");
}
int main(int argc, char **argv) {
printf("This definitely prints last. Buh Bye.\n");
}
Implementation
C++ version - static variable + constructor:
// This is some crazy magic that produces __StaticExecute__247
// Vanilla interpolation of __StaticExecute__##__LINE__ would produce __StaticExecute____LINE__
// I still can't figure out why it works, but it has to do with macro resolution ordering
// If you already have Boost, you can omit this part
#define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
#define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b)
#define BOOST_PP_CAT_II(p, res) res
// This avoids repeating the BOOST_PP_CAT 5X
#define STATIC_EXECUTE \
STATIC_EXECUTE_I(BOOST_PP_CAT(__StaticExecute__, __LINE__))
// This is the meat, a static instance of a class whose constructor runs your code
#define STATIC_EXECUTE_I(uniq_name) \
static struct uniq_name { \
uniq_name(); \
} BOOST_PP_CAT(uniq_name, __var); \
uniq_name::uniq_name() // followed by { ... }
C version - static variable + function
// ...
// The meat: a static variable initialized from a function call
#define STATIC_EXECUTE_I(uniq_name) \
static void uniq_name (); \
static int BOOST_PP_CAT(uniq_name, __var) = \
(uniq_name(), 0); \
static void uniq_name() // followed by { ... }
Notes
IMHO, the C++ version is slightly more elegant. In-theory, it consumes slightly less space. Otherwise, potato, po-tat-oh.
Caveat: I haven't tested the "C" version on a proper C-only compiler. Fingers crossed; post a note if it doesn't work.
Caveat: Compiler portability in general is a tricky thing. I wouldn't be shocked if there's a bug on some other compiler.
The BOOST_PP_CAT code is stolen from boost/preprocessor/cat.hpp. I simplified the implementation, and in the process may have compromised portability. If it doesn't work, try the original (more verbose) implementation, and post a comment below. Or, if you are already using Boost, you can just use their version.
If you are trying to understand the Boost magic, note that (at least for me, and in this scenario), the following also seems to work:
#define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
#define BOOST_PP_CAT_I(a, b) a ## b
I have a logger class. Call it MyLogger. I may use it in a function like this:
void MyFunc(MyLogger& oLogger)
{
//Do stuff
oLogger.Log("In MyFunc : Some Error");
//Do something else
oLogger.Log("In MyFunc : Some other error");
}
Now, I want to prepend "In MyFunc" to the logs if the log comes from inside MyFunc. Similarly for other functions...
Because this is tiresome, I tried something like this:
void MyLogger::PushPrependString(const char*)
{
//Store prepend string in stack and set it as current prepend string.
}
void MyLogger::PopPrependString()
{
//Pop the most recent prepend string.
}
Now, I can use these two functions like this:
void MyFunc(MyLogger& oLogger)
{
oLogger.PushPrependString("In MyFunc : ");
//Do stuff
oLogger.Log("Some Error");
//Do something else
oLogger.Log("Some other error");
oLogger.PopPrependString();
}
The trouble is, if there are multiple returns in a function, this becomes ugly. Is there any way around this? Is this a common problem? Is there any preprocessor macro like __FILE__ or __LINE__ for getting the name of the function a line appears in? Any comments would be appreciated. Thanks.
"The trouble is, if there are multiple returns in a function, this becomes ugly. Is there any way around this?"
Yes, just use an object with constructor (calls PushPrependString) and destructor (calls PopPrependString).
class LogPrefix
{
private:
MyLogger* logger_;
LogPrefix( LogPrefix const& ); // No such.
LogPrefix& operator=( LogPrefix const& ); // No such.
public:
LogPrefix( MyLogger& logger, char const s[] )
: logger_( &logger )
{
logger_->PushPrependString( s );
}
~LogPrefix()
{
logger_->PopPrependString();
}
};
Disclaimer: off the cuff code, not touched by compiler's hands...
"Is this a common problem?"
Yes.
"Is there any preprocessor macro like FILE or LINE for getting the name of the function a line appears in?"
Not in C++98. Various compilers offer various extensions that do that. IIRC C++0x adopts the C99 scheme, which unfortunately just provides static strings.
Cheers & hth.
RAII - Resource Acquisition Is Initialization.
In this case, you create an object on entry to the function that identifies the current function to the logging system; when the function exits (by any return or by exception thrown or by exception not caught), the object will be destroyed, and the destructor changes what is printed in future by the logging system.
In C99, and maybe in some C++ compilers such as G++, there is a predefined variable, __func__ containing the function name. The C++ equivalent is more complex, I believe.