Цель
Допустим, вы хотите следующее:
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");
}
Реализация
Версия C ++ - статическая переменная + конструктор:
// 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 версия - статическая переменная + функция
// ...
// 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 { ... }
Примечания
ИМХОВерсия C ++ немного элегантнее.Теоретически он занимает немного меньше места.В противном случае, potato, po-tat-oh.
Предостережение: Я не проверял версию "C" на подходящем компиляторе только для C.Скрещенные пальцы;опубликовать заметку, если она не работает.
Предостережение: переносимость компилятора в общем сложная вещь.Я не был бы шокирован, если есть ошибка в каком-то другом компиляторе.
Код BOOST_PP_CAT украден из boost / preprocessor / cat.hpp .Я упростил реализацию, и в процессе может скомпрометировать переносимость.Если это не работает, попробуйте оригинальную (более детальную) реализацию и оставьте комментарий ниже.Или, если вы уже используете Boost, вы можете просто использовать их версию.
Если вы пытаетесь понять магию Boost, учтите это (по крайней мере для меня и в этом сценарии)), похоже, также работает следующее:
#define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
#define BOOST_PP_CAT_I(a, b) a ## b