Здравствуйте, Аноним, Вы писали:
А>В статье по реализации делегатов на С++ надо было получить лексему через макросы:
А>А>#define SUFFIX 5
А>#define COMBINE(a,b) COMBINE1(a,b)
А>#define COMBINE1(a,b) a##b
А>#define I_DELEGATE COMBINE(IDelegate, SUFFIX)
А>#define C_STATIC_DELEGATE COMBINE(CStaticDelegate, SUFFIX)
А>#define C_METHOD_DELEGATE COMBINE(CMethodDelegate, SUFFIX)
А>#define C_DELEGATE COMBINE(CDelegate, SUFFIX)
А>
А>К чему здесь COMBINE1? Я согласен, что в ином случае код не компилиться...
А>Вроде бы вот что происходит:
А>1) Строчка
А>А>#define I_DELEGATE COMBINE(IDelegate, SUFFIX)
А>
А>меняеться на
А>А>#define I_DELEGATE COMBINE(IDelegate, 5)
А>
А>2) Потом, когда в где-нибудь в коде встретиться I_DELEGATE (или др.), то выполниться макром
А>А>#define COMBINE(a,b) COMBINE1(a,b)
А>
А>но ведь если a — это I_DELEGATE и b — это 5, то вполне возможно написать и такое:
А>А>#define COMBINE(a,b) a##b
А>
А>Но я уверен, что заюлуждаюсь, т.к. это неправельно... Зачем все-таки нужен этот промежуточный макрос?
Читай 16.3.1/1. Если некоторые вхождения некоторых параметров макроса являются операндами операторов '##' или '#', то внутри этих вхождений
не производится раскрытие макросов (которые могут там содержаться). Предположим, макрос 'COMBINE' объявлен вот так
#define COMBINE(a, b) a b a##b
и пытаемся применить этот макрос со следующими аргументами
#define ARG1 10
#define ARG2 20
COMBINE(ARG1, ARG2)
При выполнении макроподстановки параметров 'a' и 'b' макроса 'COMBINE' препроцессор позаботится о том, чтобы выполнить раскрытие макросов, содержащихся в параметрах 'a' и 'b',
только в первых вхождениях этих параметров, и 'a b' будет заменено на '10 20'. А вот для вторых вхождений такого раскрытия делаться
не будет, т.к. эти вхождения являются аргументами оператора '##', и 'a##b' будет заменено на 'ARG1ARG2'. Финальный результат будет таким: '10 20 ARG1ARG2'. В большинстве случаев это не то, что нужно.
Чтобы избежать вышеописанной проблемы применние оператора '##' выносят из основного макроса путем введения промежуточного макроса
#define COMBINE1(a, b) a##b
#define COMBINE(a, b) a b COMBINE1(a,b)
Теерь при выполнении макроподстановки макроса 'COMBINE' все параметры будут полностью раскрыты, т.к. ни один параметр не соседствует с оператором '##'. 'COMBINE(ARG1, ARG2)' заменится на '10 20 COMBINE1(10,20)'. Далее произойдет раскрытие макроса 'COMBINE1' и финальный результат будет иметь вид '10 20 1020'.
Вот поэтому в твоем случае и применен двухуровневый макрос.
В статье по реализации делегатов на С++ надо было получить лексему через макросы:
#define SUFFIX 5
#define COMBINE(a,b) COMBINE1(a,b)
#define COMBINE1(a,b) a##b
#define I_DELEGATE COMBINE(IDelegate, SUFFIX)
#define C_STATIC_DELEGATE COMBINE(CStaticDelegate, SUFFIX)
#define C_METHOD_DELEGATE COMBINE(CMethodDelegate, SUFFIX)
#define C_DELEGATE COMBINE(CDelegate, SUFFIX)
К чему здесь COMBINE1? Я согласен, что в ином случае код не компилиться...
Вроде бы вот что происходит:
1) Строчка
#define I_DELEGATE COMBINE(IDelegate, SUFFIX)
меняеться на
#define I_DELEGATE COMBINE(IDelegate, 5)
2) Потом, когда в где-нибудь в коде встретиться I_DELEGATE (или др.), то выполниться макром
#define COMBINE(a,b) COMBINE1(a,b)
но ведь если a — это I_DELEGATE и b — это 5, то вполне возможно написать и такое:
#define COMBINE(a,b) a##b
Но я уверен, что заюлуждаюсь, т.к. это неправельно... Зачем все-таки нужен этот промежуточный макрос?