Есть ли способ определить макрос, содержащий #include
директива в его теле?
Если я просто поставлю
"#include" выдает ошибку
C2162: "expected macro formal parameter"
поскольку здесь я не использую # для объединения строк.
Если я использую «\# include», то получаю следующие две ошибки:
error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion
Любая помощь?





Зачем макросу нужен #include? если вы # включаете любой файл, в котором находится макрос, вы можете просто поместить #include над макросом со всеми остальными операторами #include, и все должно быть красиво и изящно.
Я не вижу причин для включения в макрос чего-либо, что нельзя просто включить в файл.
Я считаю, что препроцессор C / C++ выполняет только один проход по коду, поэтому я не думаю, что это сработает. Вы могли бы получить макрос "#include", который будет вставлен в код, но компилятор подавится этим, поскольку не знает, что с этим делать. Для того, что вы пытаетесь сделать, препроцессор должен будет выполнить второй проход по файлу, чтобы подобрать #include.
Заражение - это правильно, если вы делаете:
myFile.c:
#include "standardAppDefs.h"
#myStandardIncludeMacro
standardAppDefs.h:
#define myStandardIncludeMacro #include <foo.h>
Почему бы просто не сказать:
myFile.c:
#include "standardAppDefs.h"
standardAppDefs.h:
#include <foo.h>
А макросы забыть?
Думаю, вы правы в том, что эта задача кажется невыполнимой, поскольку я тоже получил
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#
No, preprocessor directives in C++ (and C) are not reflective.
Pawel Dziepak
В любом случае, причина этой попытки в том, что я пытаюсь сделать следующее неоднократно использовал фрагмент кода в качестве макроса:
void foo(AbstractClass object)
{
switch (object.data_type())
{
case AbstractClass::TYPE_UCHAR :
{
typedef unsigned char PixelType;
#include "snippets/foo.cpp"
}
break;
case AbstractClass::TYPE_UINT:
{
typedef unsigned int PixelType;
#include "snippets/foo.cpp"
}
break;
default:
break;
}
}
Для другой задачи мне нужна аналогичная функция
void bar(AbstractClass object)
где я размещу
#include "snippets/bar.cpp"
и, конечно же, именно в "snippets / foo.cpp" и "snippets / bar.cpp" написан код для конкретной задачи.
Вам, вероятно, следует взглянуть на шаблоны (как предлагает stbuton). Вы, безусловно, должны постараться избежать этого.
как правило, вам, вероятно, следует поместить все операторы #include в одно и то же место (обычно вверху). это упрощает обслуживание и отладку вашего кода.
У меня есть немного сумасшедший способ делать в основном то, что вы хотите (используя препроцессор); посмотри мой ответ :) stackoverflow.com/a/27830271/1447953
Я не буду спорить о его достоинствах, но freetype (www.freetype.org) делает следующее:
#include FT_FREETYPE_H
где они определяют FT_FREETYPE_H в другом месте
Это явно разрешено в стандартах и, следовательно, переносимо, пока FT_FREETYPE_H расширяется до формы <header.h> или "header.h".
+1, поскольку это позволяет избежать зависимости от поведения, определенного реализацией, даже если это означает, что вы очень доверяете своей системе сборки.
Я понятия не имею, что вы на самом деле пытаетесь сделать, но похоже, что вам может понадобиться шаблонная функция.
Таким образом, PixelType является просто параметром шаблона для блока кода.
Я тоже хотел это сделать, и вот почему:
Некоторые файлы заголовков (особенно mpi.h в OpenMPI) работают по-другому, если вы компилируете на C или C++. Я связываюсь с кодом C MPI из моей программы на C++. Чтобы включить заголовок, я делаю обычное дело:
extern "C" {
#include "blah.h"
}
Но это не работает, потому что __cplusplus все еще определен даже в связи C. Это означает, что mpi.h, который включен в blah.h, начинает определять шаблоны, и компилятор умирает, говоря, что вы не можете использовать шаблоны с привязкой C.
Следовательно, что мне нужно сделать в blah.h, так это заменить
#include <mpi.h>
с
#ifdef __cplusplus
#undef __cplusplus
#include <mpi.h>
#define __cplusplus
#else
#include <mpi.h>
#endif
Примечательно, что эту патологию делает не только mpi.h. Следовательно, я хочу определить макрос INCLUDE_AS_C, который выполняет вышеуказанное для указанного файла. Но я думаю, это не сработает.
Если кто-то может придумать другой способ добиться этого, дайте мне знать.
Псевдомакросы, которые я описываю в своем ответе, позволят вам это сделать :). Синтаксис не такой красивый, как у обычного макроса, но он сработает :). В итоге вы получите что-то вроде "#define FILENAME <mpi.h>", "#include include_as_c.hpp", "#undef FILENAME" с вашим особым способом включения в include_as_c.hpp. stackoverflow.com/questions/266501/…
Языки C и C++ явно запрещают формирование директив препроцессора в результате расширения макроса. Это означает, что вы не можете включить директиву препроцессора в список замены макроса. И если вы попытаетесь обмануть препроцессор, «построив» новую директиву препроцессора с помощью конкатенации (и подобных трюков), поведение будет неопределенным.
Итак, как говорят другие, нет, у вас не может быть операторов #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
Я нечасто использовал этот трюк, но он выполняет свою работу. Очевидно, что его можно расширить, чтобы иметь столько «параметров», сколько необходимо, и вы можете запускать там любые команды препроцессора, которые вам нравятся, а также генерировать фактический код. Вы просто не можете использовать материал, который он создает, в качестве входных данных для другого макроса, как вы можете с обычными макросами, поскольку вы не можете вставить include внутри макроса. Но он может войти в другой псевдомакрос :).
У других могут быть комментарии по поводу других ограничений и того, что может пойти не так :).
Звучит здорово, но теоретически это не определено в стандарте и зависит от реализации компилятора. См. stackoverflow.com/questions/20524491/…
Замечательно. Что я действительно хотел бы сделать, так это добавить #define в include, чтобы у меня были макросы, определяющие макросы. От этого выиграют такие вещи, как Openssl STACK_OF. Это должно было быть в стандарте C давно, но лобби «макросы - это зло», похоже, победило. Поэтому вместо этого мы используем Perl, не менее злой.
Хм, не так ли? Вы можете определить все, что хотите, во включенном файле, и он должен работать как обычно.
Это не работает, и "#myStandardIncludeMacro" является ошибкой синтаксического анализа, если я не ошибаюсь.