Итак, как говорят другие, нет, вы не можете иметь операторы #include внутри макроса, поскольку препроцессор выполняет только один проход. Тем не менее, вы можете заставить препроцессор делать в основном то же самое с помощью хитрого трюка, который я недавно использовал.
Поймите, что директивы препроцессора ничего не делают внутри макроса, однако они БУДУТ что-то делать в файле. Таким образом, вы можете вставить блок кода, который хотите изменить, в файл, думая о нем как об определении макроса (с фрагментами, которые могут быть изменены другими макросами), а затем #include этот файл псевдомакроса в различных местах (make конечно, у него нет охранников!). Он не ведет себя точно так же, как макрос, но он может дать довольно похожие на макрос результаты, поскольку #include просто выгружает содержимое одного файла в другой.
Например, рассмотрите возможность включения большого количества заголовков с одинаковыми именами, которые входят в группы. Утомительно записывать их все, или, возможно, они даже генерируются автоматически. Вы можете частично автоматизировать их включение, сделав что-то вроде этого:
Заголовок вспомогательных макросов:
/* tools.hpp */
#ifndef __TOOLS_HPP__
#def __TOOLS_HPP__
// Macro for adding quotes
#define STRINGIFY(X) STRINGIFY2(X)
#define STRINGIFY2(X) #X
// Macros for concatenating tokens
#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_2 CAT
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))
#define CAT_4(A,X,Y,Z) CAT(A,CAT_3(X,Y,Z))
// etc...
#endif
Псевдомакрофайл
/* pseudomacro.hpp */
#include "tools.hpp"
// NO INCLUDE GUARD ON PURPOSE
// Note especially FOO, which we can #define before #include-ing this file,
// in order to alter which files it will in turn #include.
// FOO fulfils the role of "parameter" in this pseudo-macro.
#define INCLUDE_FILE(HEAD,TAIL) STRINGIFY( CAT_3(HEAD,FOO,TAIL) )
#include INCLUDE_FILE(head1,tail1.hpp) // expands to #head1FOOtail1.hpp
#include INCLUDE_FILE(head2,tail2.hpp)
#include INCLUDE_FILE(head3,tail3.hpp)
#include INCLUDE_FILE(head4,tail4.hpp)
// etc..
#undef INCLUDE_FILE
Исходный файл
/* mainfile.cpp */
// Here we automate the including of groups of similarly named files
#define FOO _groupA_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupA_tail1.hpp"
// #include "head2_groupA_tail2.hpp"
// #include "head3_groupA_tail3.hpp"
// #include "head4_groupA_tail4.hpp"
#undef FOO
#define FOO _groupB_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupB_tail1.hpp"
// #include "head2_groupB_tail2.hpp"
// #include "head3_groupB_tail3.hpp"
// #include "head4_groupB_tail4.hpp"
#undef FOO
#define FOO _groupC_
#include "pseudomacro.hpp"
#undef FOO
// etc.
Эти включения могут быть даже в середине блоков кодов, которые вы хотите повторить (с измененным FOO), как ответ запросов Bing Jian: определение макроса, содержащее директиву #include
Я не использовал этот трюк широко, но он выполняет свою работу. Очевидно, его можно расширить, чтобы иметь столько «параметров», сколько необходимо, и вы можете запускать там любые команды препроцессора, которые вам нравятся, а также генерировать фактический код. Вы просто не можете использовать материал, который он создает, в качестве входных данных в другой макрос, как вы можете с обычными макросами, поскольку вы не можете вставить включение в макрос. Но это может быть внутри другого псевдомакроса :).
У других могут быть комментарии по другим ограничениям и тому, что может пойти не так :).
person
Ben Farmer
schedule
07.01.2015