Экранирование символа # в макросе #define?
-
16-09-2019 - |
Вопрос
Не вдаваясь в кровавые подробности, я хочу использовать #define
макрос, который расширится до #include
но знак «#» сбивает с толку препроцессор (поскольку он думает, что я хочу процитировать аргумент.)
Например, я хочу сделать что-то вроде этого:
#define MACRO(name) #include "name##foo"
И используйте его так:
MACRO(Test)
Который расширится до:
#include "Testfoo"
Скромный знак # вызывает у препроцессора рвоту.MinGW выдает мне следующую ошибку:
'#' is not followed by a macro parameter
Думаю, мне нужно избежать знака #, но я этого не делаю, если это вообще возможно.
Да, макросы действительно зло...
Решение
Насколько я помню, вы не можете использовать другую директиву препроцессора в определении.
Другие советы
Это является можно вставить хэш-токен в предварительно обработанный поток токенов.Вы можете сделать это следующим образом:
#define MACRO(hash, name) hash include name
MACRO(#,"hello")
— расширяется до:
# include "hello"
Однако, стандарт явно исключает любой дальнейший анализ такой строки на наличие директив предварительной обработки [cpp.rescan]:
Полученная в результате полностью замененная макросом последовательность токенов предварительной обработки не обрабатывается как директива предварительной обработки, даже если она похожа на нее.
На самом деле проблема не в том, что на выходе вашего препроцессора появляется символ #.
Очевидно, вы хотите, чтобы препроцессор повторно обработал ваш файл и обработал вновь созданные директивы #include как часть расширения макроса.Это не работает таким образом.Если строка начинается с #, это инструкция для препроцессора и интерпретируется.Если строка не начинается с #, она подлежит только преобразованию препроцессора, включая макроподстановку.Это проверка один раз на строку.
MACRO(Test)
не начинается с #.Поэтому она не интерпретируется как директива препроцессора;вместо этого на него распространяются правила замены макросов.
Это связано с тем, что # имеет особое значение при использовании в макросе.
# means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.
В вашей ситуации за # не следует правильный токен.Итак, в вашей ситуации нам нужно пройти уровень косвенности:
#define QUOTE(name) #name
#define TEST(name) QUOTE(name ## foo)
#include TEST(scot)
Вы не можете этого сделать.Директивы препроцессора распознаются перед раскрытием макроса;если макрос разворачивается во что-то похожее на директиву препроцессора, эта директива не будет распознана.Лучшее, что вы можете сделать, это создать макрос для имени файла:
#define MACRO(name) "name##foo"
...
#include MACRO(Test)
Этот мощь работа (работает для обычного #define
макросы без параметров, но я не проверял это с макросами с параметрами).
#define MACRO(name) <name##foo>
#include MACRO(Test)
#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)
#define PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)
int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);