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

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

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

C2162: "expected macro formal parameter"

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
36
0
40 297
9

Ответы 9

Зачем макросу нужен #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>

А макросы забыть?

Это не работает, и "#myStandardIncludeMacro" является ошибкой синтаксического анализа, если я не ошибаюсь.

RecursiveExceptionException 07.10.2018 01:51

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

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). Вы, безусловно, должны постараться избежать этого.

Jonathan Leffler 06.11.2008 01:42

как правило, вам, вероятно, следует поместить все операторы #include в одно и то же место (обычно вверху). это упрощает обслуживание и отладку вашего кода.

helloandre 06.11.2008 04:30

У меня есть немного сумасшедший способ делать в основном то, что вы хотите (используя препроцессор); посмотри мой ответ :) stackoverflow.com/a/27830271/1447953

Ben Farmer 08.01.2015 02:17

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

#include FT_FREETYPE_H

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

Это явно разрешено в стандартах и, следовательно, переносимо, пока FT_FREETYPE_H расширяется до формы <header.h> или "header.h".

Jonathan Leffler 06.11.2008 01:42

+1, поскольку это позволяет избежать зависимости от поведения, определенного реализацией, даже если это означает, что вы очень доверяете своей системе сборки.

einpoklum 11.03.2017 00:27

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

Таким образом, 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/…

Ben Farmer 08.01.2015 02:37

Языки 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/…

Antonio 24.08.2016 16:02

Замечательно. Что я действительно хотел бы сделать, так это добавить #define в include, чтобы у меня были макросы, определяющие макросы. От этого выиграют такие вещи, как Openssl STACK_OF. Это должно было быть в стандарте C давно, но лобби «макросы - это зло», похоже, победило. Поэтому вместо этого мы используем Perl, не менее злой.

Tuntable 19.05.2017 04:01

Хм, не так ли? Вы можете определить все, что хотите, во включенном файле, и он должен работать как обычно.

Ben Farmer 19.05.2017 08:40

Другие вопросы по теме