Usage of FLAGS_nono##name in gflags source code - c++

I'm reading gflags's source code recently. And the comment here really confuses me.
It's saying FLAGS_nono##name is introduced to ensure static initialization. But as far as I know, if you define a global var like:
int x = 20;
x is still statically initialized. The what's the necessity of FLAGS_nono##name here.
Do I misunderstand it?
Thanks.
// Each command-line flag has two variables associated with it: one
// with the current value, and one with the default value. However,
// we have a third variable, which is where value is assigned; it's a
// constant. This guarantees that FLAG_##value is initialized at
// static initialization time (e.g. before program-start) rather than
// than global construction time (which is after program-start but
// before main), at least when 'value' is a compile-time constant. We
// use a small trick for the "default value" variable, and call it
// FLAGS_no<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
static #GFLAGS_NAMESPACE#::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
For more context, see
https://code.google.com/p/gflags/source/browse/src/gflags.h.in#471
Another question is the FlagRegisterer class used in the codes mentioned above.
I'm wondering what's the necessity of such class and a global var here, instead of simply defining a function.
class GFLAGS_DLL_DECL FlagRegisterer {
public:
FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage);
};
// --------------------------------------------------------------------
// FlagRegisterer
// This class exists merely to have a global constructor (the
// kind that runs before main(), that goes an initializes each
// flag that's been declared. Note that it's very important we
// don't have a destructor that deletes flag_, because that would
// cause us to delete current_storage/defvalue_storage as well,
// which can cause a crash if anything tries to access the flag
// values in a global destructor.
// --------------------------------------------------------------------
FlagRegisterer::FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage) {
if (help == NULL)
help = "";
// FlagValue expects the type-name to not include any namespace
// components, so we get rid of those, if any.
if (strchr(type, ':'))
type = strrchr(type, ':') + 1;
FlagValue* current = new FlagValue(current_storage, type, false);
FlagValue* defvalue = new FlagValue(defvalue_storage, type, false);
// Importantly, flag_ will never be deleted, so storage is always good.
CommandLineFlag* flag = new CommandLineFlag(name, help, filename,
current, defvalue);
FlagRegistry::GlobalRegistry()->RegisterFlag(flag); // default registry
}

You're right that something like int i = 10; performs static initialisation. It would therefore be possible to write
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = value; \
type FLAGS_no##name = value; \
static #GFLAGS_NAMESPACE#::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
However, please beware that this is a macro. Multiple references to value cause multiple expansions. If value is not a constant, if it contains e.g. a function call, this would cause the function to be called twice.
That could be avoided by copying one variable to the other:
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = value; \
type FLAGS_no##name = FLAGS_##name; \
static #GFLAGS_NAMESPACE#::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
But now you've got dynamic initialisation, where you'd want static initialisation.
To make sure both work properly, you need an additional helper variable, and that's what the code you're asking about does.

Related

How to avoid re-declare variables with C++ Macros

I want to write a simple Macro function. Because this macro is used in many places by different normal c++ functions, I encountered a variable scope issue. I would like to know if there is a quick way to solve it? Thank you very much.
As you can see in the attached code, depending on whether the macro is called in the function for the first time or not, I want to either declare or reuse the variable ptrCandidate. Note the variable scope is in the function, not in the file or translation unit. In other words, every time the macro is invoked in a new function for the 1st time, I want the top macro. And within the same function, if the macro is invoked again, I want the bottom macro.
#define EXPECT_MY_CLASS_EQ(expectedStr, candidateStr) \
auto ptrCandidate = parseAndGetPtr(candidateStr); \
doWork(ptrCandidate); \
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));
#define EXPECT_MY_CLASS_EQ(expectedStr, candidateStr) \
ptrCandidate = parseAndGetPtr(candidateStr); \
doWork(ptrCandidate); \
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));
void foo(){
EXPECT_MY_CLASS_EQ("123","abcd")
}
void bar(){
EXPECT_MY_CLASS_EQ("111","aabb")
EXPECT_MY_CLASS_EQ("222","ccdd")
}
void foo(){
auto ptrCandidate = parseAndGetPtr("abcd");
doWork(ptrCandidate);
EXPECT_EQ("123", convertToString(ptrCandidate));
}
void bar(){
auto ptrCandidate = parseAndGetPtr("aabb");
doWork(ptrCandidate);
EXPECT_EQ("111", convertToString(ptrCandidate));
/* auto */ ptrCandidate = parseAndGetPtr("ccdd");
doWork(ptrCandidate);
EXPECT_EQ("222", convertToString(ptrCandidate));
}
As shown in another answer, you don't need a macro in this case.
Generally speaking though, you can avoid re-definitions of variable names by the following means:
Use of __LINE__ preprocessor symbol (or __COUNTER__, though IIRC that's not standard). Note that creating a variable name with the preprocessor requires two levels of indirection (replace VARIABLE in the link with __LINE__).
A do { /* code */ } while(0) ... which is AFAIK the most common way to write macros that are more than just a simple expression.
A lambda which is immediately executed:
([](auto var) { /* code using var */ })(initExpressionForVar())
Note that each of these approaches actually creates a new variable each time, so is semantically different from your approach with two separate macros! This is especially important if the type of the (assigned) variable has a non-default assignment operator!
If, for some reason, you rely on the reuse of a single variable and the assignment to it, then IMO the easiest approach is to define two macros. One macro which declares the variable (and initializes it, if necessary), and another macro with the code which uses the variable.
It seems regular function works:
void EXPECT_MY_CLASS_EQ(const char* expectedStr, const char* candidateStr)
{
auto ptrCandidate = parseAndGetPtr(candidateStr);
doWork(ptrCandidate);
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));
}
A possible way might be to use __LINE__ or __COUNTER__ with preprocessor symbol concatenation.
In your case, you probably don't need any macro: prefer some static inline function.
Here is a real-life example (using concatenation and __LINE__) from my Bismon's project file cmacros.h line 285 (it is in C, but the same trick could be done in C++)
#define LOCAL_FAILURE_HANDLE_ATBIS_BM(Fil,Lin,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar) \
struct failurehandler_stBM fh_##Lin \
= { \
.pA = {.htyp = typayl_FailureHandler_BM}, \
.failh_magic = FAILUREHANDLEMAGIC_BM, \
.failh_lockset = Lockset, \
.failh_reason = NULL, \
.failh_jmpbuf = {}}; \
curfailurehandle_BM = &fh_##Lin; \
volatile int failcod_##Lin = setjmp(fh_##Lin.failh_jmpbuf); \
FcodVar = failcod_##Lin; \
if (failcod_##Lin) { \
ReasonVar = fh_##Lin.failh_reason; \
PlaceVar = fh_##Lin.failh_place; \
goto Flabel; \
}; \
(void)0
#define LOCAL_FAILURE_HANDLE_AT_BM(Fil,Lin,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar) \
LOCAL_FAILURE_HANDLE_ATBIS_BM(Fil,Lin,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar)
/// code using LOCAL_FAILURE_HANDLE_BM should probably backup and
/// restore the curfailurehandle_BM
#define LOCAL_FAILURE_HANDLE_BM(Lockset,Flabel,FcodVar,ReasonVar,PlaceVar) \
LOCAL_FAILURE_HANDLE_AT_BM(__FILE__,__LINE__,Lockset,Flabel,FcodVar,ReasonVar,PlaceVar)
Back to your question, if you still want a macro: just create a block, e.g.
#define EXPECT_MY_CLASS_EQ(expectedStr, candidateStr) do{ \
auto ptrCandidate = parseAndGetPtr(candidateStr); \
doWork(ptrCandidate); \
EXPECT_EQ(expectedStr, convertToString(ptrCandidate));} while(0)

Is it possible to detect whether a local variable declared?

Is it possible to detect whether a local variable declared?
The reason is that I'd like to have a macro (LOG), which has a logic like this:
if (<logContext is declared>) {
log(logContext, <parameters>);
} else {
DefaultLogContext logContext(*this);
log(logContext, <parameters>);
}
So, if the macro sees that there is a local variable named logContext, then it passes this variable to log. If logContext doesn't exist, then it creates a default logContext, and passes that to log.
Note: DefaultLogContext is a dependent type. It means that this logging macro can only be used in a class member function, and this type is a typedef to an actual type-dependent LogContext class:
class File {
typedef FileLogContext DefaultLogContext;
void open() {
LOG("open"); // here, I'd like LOG to create a new local logContext
}
void complexFunction() {
FileLogContext logContext(...);
logContext.setup();
LOG("pass1"); // here, I'd like LOG to use my declared logContext
pass1();
LOG("pass2"); // same comment as at pass1
pass2();
// other LOG and pass function calls here
};
Somewhat ugly solution that checks for a presence of local variable named local_context:
#include <iostream>
#include <type_traits>
constexpr class t_Decoy{} const local_context; // should be declared in global scope
class t_Context{};
#define LOG(text) \
[&](char const * const psz_text) -> void \
{ \
if constexpr(::std::is_same_v<t_Context, decltype(local_context)>) \
{ \ // we can use captured local_context here
::std::cout << psz_text << " has local_context" << ::std::endl; \
} \
else \
{ \ // we can create default context using captured this
::std::cout << psz_text << " no local_context" << ::std::endl; \
}\
}(text)
int main()
{
LOG("first");
t_Context local_context{};
LOG("second");
}
online compiler
No. Without reflection you cannot do such a thing autonomously. Then again, it would be of little benefit here.
Instead you should simply restructure your macros. You know, as the programmer, whether a variable is in scope at the point where you write your macro, and can instead use a different macro that does not require an extant variable.
You won't be able to do this via local variables. If you need an RAII style scoped logging facility, you have no choice but to create a local object explicitly.
LogScope logscope("some log msg");
If you don't need RAII, then you could have a global log object that maps __FUNCTION__ (or so) to a log context.
#define LOG(msg) { \
auto& logScope = g_logManager[__FUNCTION__]; \
}

Confusing macro definition in C++

Recently,I am reading some code from B-Human and I ecountered this confusing snippet:
void enumInit(char* enums, const char** names, int numOfEnums);
#define ENUM(Enum, ...) \
enum Enum : unsigned char {__VA_ARGS__, numOf##Enum##s}; \
inline static const char* getName(Enum e) \
{ \
static char enums[] = #__VA_ARGS__; \
static const char* names[numOf##Enum##s]; \
static bool init = true; \
if(init) \
{ \
enumInit(enums, names, numOf##Enum##s); \
init = false; \
} \
return e >= numOf##Enum##s ? 0 : names[e]; \
}
I cannot understand how this macro works, how could it be a function definition in a macro definition? It is a single cpp header file with #pragma once.
void enumInit(char* enums, const char** names, int numOfEnums);
Isn't defined anywhere in the code you posted, so strictly speaking I don't know what it does.
#define ENUM(Enum, ...) \
enum Enum : unsigned char {__VA_ARGS__, numOf##Enum##s}; \
This defines an enum with the values passed to the macro as "..." (google "variadic macro") as values, and an additional entry whose value is the number of elements in that macro and whose name is the concatenation of "numOf", the value of Enum (passed as a parameter) and "s". This last value is the entry with both value and position n if the enum contains n other values (starting at 0).
inline static const char* getName(Enum e) \
{ \
static char enums[] = #__VA_ARGS__; \
static const char* names[numOf##Enum##s]; \
static bool init = true; \
if(init) \
{ \
enumInit(enums, names, numOf##Enum##s); \
init = false; \
} \
return e >= numOf##Enum##s ? 0 : names[e]; \
}
This defines an inline function whereever your macro is called. It defines a static array containing the stringified value of the of the enum entries (enums[]), and their names (names[...]). On the first fall, enumInit(...) is called. Likely, this function fills the names array with the names of the respective enum values. For this, the string stored inside enums[] is used. To know how exactly that works, I would need to know the definition of enumInit.
edit: To more clearly answer the how could it be a function defination in a macro defination? part of your question: The macro itself is just pasted wherever it is used. The function definition is inserted whereever it is called, so that one function is generated per macro call.

Rare cases where MACROs must be used

Debugging macros can take a lot of time. We are much better off
avoiding them except in the very rare cases when neither constants,
functions nor templates can do what we want.
What are the rare cases?
If you want actual textual replacement, that's where you use macros. Take a look at Boost.Preprocessor, it's a great way to simulate variadic templates in C++03 without repeating yourself too much.
In other words, if you want to manipulate the program code itself, use macros.
Another useful application is assert, which is defined to be a no-op when NDEBUG is not defined (usually release mode compilation).
That brings us to the next point, which is a specialization of the first one: Different code with different compilation modes, or between different compilers. If you want cross-compiler support, you can't get away without macros. Take a look at Boost in general, it needs macros all the time because of various deficiencies in various compilers it has to support.
Another important point is when you need call-site information without wanting to bug the user of your code. You have no way to automatically get that with just a function.
#define NEEDS_INFO() \
has_info(__FILE__, __LINE__, __func__)
With a suitable declaration of has_info (and C++11/C99 __func__ or similar).
This question doesn't appear to have a definite, closed-form answer, so I'll just give a couple of examples.
Suppose you want to print information about a given type. Type names don't exist in the compiled code, so they cannot possibly be expressed by the language itself (except for C++ extensions). Here the preprocessor must step in:
#define PRINT_TYPE_INFO(type) do { printf("sizeof(" #type ") = %zu\n", sizeof(type)); } while (false)
PRINT_TYPE_INFO(int);
PRINT_TYPE_INFO(double);
Similarly, function names are not themselves variable, so if you need to generate lots of similar names, the preprocessor helps:
#define DECLARE_SYM(name) fhandle libfoo_##name = dlsym("foo_" #name, lib);
DECLARE_SYM(init); // looks up "foo_init()", declares "libfoo_init" pointer
DECLARE_SYM(free);
DECLARE_SYM(get);
DECLARE_SYM(set);
My favourite use is for dispatching CUDA function calls and checking their return value:
#define CUDACALL(F, ARGS...) do { e = F(ARGS); if (e != cudaSuccess) throw cudaException(#F, e); } while (false)
CUDACALL(cudaMemcpy, data, dp, s, cudaMemcpyDeviceToHost);
CUDACALL(cudaFree, dp);
Since this an Open ended Question an trick which I often use and find convenient.
If you want to write an wrapper function over an free function like say malloc, without modifying each and every instance in your code where the function is called then a simple macro shall suffice:
#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)
void* my_malloc(size_t size, const char *file, int line, const char *func)
{
void *p = malloc(size);
printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);
/*Link List functionality goes in here*/
return p;
}
You can often use this trick to write your own memory leak detector etc, for debugging purposes.
Though the example is for malloc it can be re-used for any free standing function really.
One example is token pasting if you want to use a value as both an identifier and a value. From the msdn link:
#define paster( n ) printf_s( "token" #n " = %d", token##n )
int token9 = 9;
paster( 9 ); // => printf_s( "token9 = %d", token9 );
There are also cases in the c++ faq where though there may be alternatives the macro solution is the best way to do things. One example is pointers to member functions where the right macro
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
makes it much easier to make the call rather than deal with all the assorted hair of trying to do it w/out the macro.
int ans = CALL_MEMBER_FN(fred,p)('x', 3.14);
Honestly I just take their word for it and do it this way, but apparently it gets worse as the calls become more complicated.
Here's an example of someone trying to go it alone
When you need the call itself to optionally return from a function.
#define MYMACRO(x) if(x) { return; }
void fn()
{
MYMACRO(a);
MYMACRO(b);
MYMACRO(c);
}
This is usually used for small bits of repetitive code.
I am not sure that debugging macros take a lot of time. I would believe that I find simple the debugging of macros (even 100 lines monster macros), because you have the possibility to look at the expansion (using gcc -C -E for instance) - which is less possible with e.g. C++ templates.
C macros are useful when in several occasions:
you want to process a list of things in several different ways
you want to define an "lvalue" expression
you need efficiency
you need to have the location of the macro thru __LINE__)
you need unique identifiers
etc etc
Look at the many uses of #define-d macros inside major free softwaare (like Gtk, Gcc, Qt, ...)
What I regret a lot is that C macro language is so limited.... Imagine if the C macro language would have been as powerful as Guile!!! (Then you could write things as complex as flex or bison as macros).
Look at the power of Common Lisp macros!
If you are using C, you need to use macros to simulate templates.
From http://www.flipcode.com/archives/Faking_Templates_In_C.shtml
#define CREATE_VECTOR_TYPE_H(type) \
typedef struct _##type##_Vector{ \
type *pArray; \
type illegal; \
int size; \
int len; \
} type##_Vector; \
void type##_InitVector(type##_Vector *pV, type illegal); \
void type##_InitVectorEx(type##_Vector *pV, int size, type illegal); \
void type##_ClearVector(type##_Vector *pV); \
void type##_DeleteAll(type##_Vector *pV); \
void type##_EraseVector(type##_Vector *pV); \
int type##_AddElem(type##_Vector *pV, type Data); \
type type##_SetElemAt(type##_Vector *pV, int pos, type data); \
type type##_GetElemAt(type##_Vector *pV, int pos);
#define CREATE_VECTOR_TYPE_C(type) \
void type##_InitVector(type##_Vector *pV, type illegal) \
{ \
type##_InitVectorEx(pV, DEF_SIZE, illegal); \
} \
void type##_InitVectorEx(type##_Vector *pV, int size, type illegal) \
{ \
pV-len = 0; \
pV-illegal = illegal; \
pV-pArray = malloc(sizeof(type) * size); \
pV-size = size; \
} \
void type##_ClearVector(type##_Vector *pV) \
{ \
memset(pV-pArray, 0, sizeof(type) * pV-size); \
pV-len = 0; \
} \
void type##_EraseVector(type##_Vector *pV) \
{ \
if(pV-pArray != NULL) \
free(pV-pArray); \
pV-len = 0; \
pV-size = 0; \
pV-pArray = NULL; \
} \
int type##_AddElem(type##_Vector *pV, type Data) \
{ \
type *pTmp; \
if(pV-len = pV-size) \
{ \
pTmp = malloc(sizeof(type) * pV-size * 2); \
if(pTmp == NULL) \
return -1; \
memcpy(pTmp, pV-pArray, sizeof(type) * pV-size); \
free(pV-pArray); \
pV-pArray = pTmp; \
pV-size *= 2; \
} \
pV-pArray[pV-len] = Data; \
return pV-len++; \
} \
type type##_SetElemAt(type##_Vector *pV, int pos, type data) \
{ \
type old = pV-illegal; \
if(pos = 0 && pos <= pV-len) \
{ \
old = pV-pArray[pos]; \
pV-pArray[pos] = data; \
} \
return old; \
} \
type type##_GetElemAt(type##_Vector *pV, int pos) \
{ \
if(pos = 0 && pos <= pV-len) \
return pV-pArray[pos]; \
return pV-illegal; \
}
Consider the standard assert macro.
It uses conditional compilation to ensure that the code is included only in debug builds (rather than relying on the optimizer to elide it).
It uses the __FILE__ and __LINE__ macros to create references to the location in the source code.
I've once used macro to generate a large string array along with index enumeration:
strings.inc
GEN_ARRAY(a)
GEN_ARRAY(aa)
GEN_ARRAY(abc)
GEN_ARRAY(abcd)
// ...
strings.h
// the actual strings
#define GEN_ARRAY(x) #x ,
const char *strings[]={
#include "strings.inc"
""
};
#undef GEN_ARRAY
// indexes
#define GEN_ARRAY(x) enm_##x ,
enum ENM_string_Index{
#include "strings.inc"
enm_TOTAL
};
#undef GEN_ARRAY
It is useful when you have several array that has to be kept synchronized.
To expand on #tenfour's answer about conditional returns: I do this a lot when writing Win32/COM code where it seems I'm checking an HRESULT every second line. For example, compare the annoying way:
// Annoying way:
HRESULT foo() {
HRESULT hr = SomeCOMCall();
if (SUCCEEDED(hr)) {
hr = SomeOtherCOMCall();
}
if (SUCCEEDED(hr)) {
hr = SomeOtherCOMCall2();
}
// ... ad nauseam.
return hr;
}
With the macro-y nice way:
// Nice way:
HRESULT foo() {
SUCCEED_OR_RETURN(SomeCOMCall());
SUCCEED_OR_RETURN(SomeOtherCOMCall());
SUCCEED_OR_RETURN(SomeOtherCOMCall2());
// ... ad nauseam.
// If control makes it here, nothing failed.
return S_OK;
}
It's doubly handy if you wire up the macro to log any failures automatically: using other macro ideas like token pasting and FILE, LINE, etc; I can even make the log entry contain the code location and the expression that failed. You could also throw an assert in there if you wanted to!
#define SUCCEED_OR_RETURN(expression) { \
HRESULT hrTest = (expression); \
if (!SUCCEEDED(hrTest)) { \
logFailure( \
#expression, \
HResultValueToString(hrTest), \
__FILE__, \
__LINE__, \
__FUNCTION__); \
return hrTest; \
} \
}
Debugging would be much easier as your project will be in divided into various modules for each task. Macros can be very useful when you have a large and complex software project. But there are some pitfalls which are stated here.
For me it's more comfortable to use macros for constants and for parts of code that have no separated logical functionality. But there are some important differences between (inline) functions and (function-like) macros, here they are:
http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx

Calling a function immediately before main

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