O_oI need to define a macro in a header file in C++ which is called lots of time in the application (for particular, thus non-negociable, log reasons).
The C++ language doesn't guarantee order of initialization of global objects.
The C++ language only guarantees order of destruction regarding `std::atexit` with respect to construction of global or `static` objects not the use of any such objects.
The C++ language has no concept of a "phoenix" lifetimes so a destroyed global or `static` object must not be used which complicates any usage by any other global or `static` objects.
The easiest way to resolve all of the related problems is with an interface which pretends that opening, writing, and then closing a file is a single atomic operation.
I have no issues with using a macro for logging if you allow builds without any logging, but I'd argue that you should still be using a named `inline` function within the definition of such a macro.I have quickly read that this is possible by defining a class in the header, with diffferent possibilities for the instantiation.
You could solve that particular issue with a normal `inline` function yielding a reference or pointer to a constructed `std:fstream` object.I considered that for my example, but then there would be (potentially) one copy for every translation unit that included the header. Still an improvement over opening and closing on every call though.
Soma
Code:#include <cstdlib> #include <iostream> #include <string> #if !defined(__PRETTY_FUNCTION__) # define __PRETTY_FUNCTION__ __PRETTY_FUNCTION__ #endif //?! (__PRETTY_FUNCTION__) struct SExample { SExample(): m(1) { std::cout << __PRETTY_FUNCTION__ << ": " << m << "\n"; }; ~SExample() { std::cout << __PRETTY_FUNCTION__ << ": " << m << "\n"; --m; }; void doSomething() { std::cout << __PRETTY_FUNCTION__ << ": " << m << "\n"; } int m; }; void DoSomething1 ( const char * f ) { static SExample s; std::cout << __PRETTY_FUNCTION__ << ": " << f << "\n"; s.doSomething(); } void DoSomething2() { std::cout << __PRETTY_FUNCTION__ << "\n"; DoSomething1("use static `s` in the `DoSomething2` function"); } int main ( int argc , char ** argv ) { if((argc > 1) && (std::string("misordered") == argv[1])) { // register a function *before* `s` is constructed std::atexit(DoSomething2); DoSomething1("use static `s` in the `main` function"); } else { DoSomething1("use static `s` in the `main` function"); // register a function *after* `s` is constructed std::atexit(DoSomething2); } return(0); }