Подтвердить что ты не робот

Определение макроса, содержащее директиву #include

Есть ли способ определить макрос, который может содержать #include директива в ее теле?

Если я просто поставлю "#include", он дает ошибку

C2162: "expected macro formal

Параметр "

так как здесь я не использую # для конкатенации строк.
Если я использую "\# include", я получаю следующие две ошибки:

error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion

Любая помощь?

4b9b3361

Ответ 1

Так, как говорят другие, нет, у вас не может быть операторов #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

Pseudo-macro file

/* 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

Я не использовал этот трюк широко, но он выполняет мою работу. Очевидно, что он может быть расширен, чтобы иметь столько "параметров", сколько необходимо, и вы можете запускать любые команды препроцессора, которые вам нравятся, плюс генерировать фактический код. Вы просто не можете использовать материал, который он создает, как ввод в другой макрос, как вы можете с помощью обычных макросов, так как вы не можете вставлять внутри макроса. Но он может войти в другой псевдомакро:).

Другие могут иметь некоторые комментарии к другим ограничениям, и что может пойти не так:).

Ответ 2

Я не буду спорить о его достоинствах, но freetype (www.freetype.org) делает следующее:

#include FT_FREETYPE_H

где они определяют FT_FREETYPE_H в другом месте

Ответ 3

Языки

C и С++ явно запрещают формирование директив препроцессора в результате расширения макросов. Это означает, что вы не можете включить директиву препроцессора в список замены макросов. И если вы попытаетесь обмануть препроцессор, "построив" новую директиву препроцессора посредством конкатенации (и трюки), поведение undefined.

Ответ 4

Я считаю, что препроцессор C/С++ выполняет только один проход над кодом, поэтому я не думаю, что это сработает. Возможно, вы сможете получить "#include", который будет помещен в код макросом, но компилятор задушит его, поскольку он не знает, что с этим делать. Для того, что вы пытаетесь сделать для работы, препроцессор должен будет сделать второй проход над файлом, чтобы получить #include.

Ответ 5

Я тоже хотел это сделать, и вот причина:

Некоторые файлы заголовков (особенно mpi.h в OpenMPI) работают по-разному, если вы компилируете на C или С++. Я связываюсь с кодом C MPI из моей программы на С++. Чтобы включить заголовок, я делаю обычное:

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, который делает выше для указанного файла. Но я думаю, что это не сработает.

Если кто-то может понять другой способ выполнения этого, сообщите мне.

Ответ 6

Я думаю, что вы в порядке, потому что эта задача кажется невозможной, поскольку я также получил от

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#

Нет, директивы препроцессора в С++ (и C) не являются отражающими.

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" записывается код, специфичный для конкретной задачи.

Ответ 7

Зачем макросу нужно иметь #include? если вы # включаете какой-либо файл, в котором находится макрос, вы можете просто положить #include над макросом со всеми остальными операторами #include, и все должно быть красивым и денди.

Я не вижу причины, чтобы макрос включал все, что не могло быть просто включено в файл.

Ответ 8

Я понятия не имею, что вы на самом деле пытаетесь сделать, но похоже, что вам может понадобиться шаблонная функция.

Таким образом, PixelType является всего лишь параметром шаблона блока кода.

Ответ 9

Контагиозный - это правильно - если вы делаете:

myFile.c:

#include "standardAppDefs.h"
#myStandardIncludeMacro

standardAppDefs.h:

#define myStandardIncludeMacro #include <foo.h>

Почему бы просто не сказать:

myFile.c:

#include "standardAppDefs.h"

standardAppDefs.h:

#include <foo.h>

И забыли макросы?