ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Среда
10 июля
311921
fk0, легенда (02.03.2012 20:23, просмотров: 2746)
#define FOREACH(M, ...) -- можно ли написать в C99 макрос, который для переменного (путь ограниченного, небольшого) списка аргументов применял бы другой заданный макрос M(argument). Как? Совершенно точно известно, что можно, но реализация исключительно страшна (как и умом не постижима). Ну а если число аргументов не больше 20, можно попроще как-то? Известен, например, макрос считающий число аргументов (ограниченное множество аргументов) ему переданных. Соответственно можно написать M##ARGS_COUNT(__VA_ARGS__) (__VA_ARGS__) и написать штук двадцать M1, M2...M20(a1, a2...a20) M-макросов под разное число аргументов. А нельзя ли (нельзя), но хочется рекурсии, чтоб руками не писать... Например можно написать #define M7(...) M4(__VA_ARGS__) M3(shift(shift(shift(__VA_ARGS__)))), где shift -- сдвигает влево, теряя самый первый аргумент. Но не выйдет: результат shift'а будет не списоком аргументов, а одним аргументом текстовой строкой, где через запятую перечислены все аргументы (т.е. он из списка делает строку, любой макрос так делает при подстановке -- не понимаю, кстати, почему). А написать #define shift(macro, v, ...) macro(__VA_ARGS__) тоже нельзя, потому, что при применении более одного shift подряд образуется рекурсия. Как быть? И почему для shift'а происходит объединение всех аргументов в единую строку -- подстановка M(shift(1,2,3,4)) с точки зрения M даёт один аргумент, хотя shift съедает лишь единицу: #define shift(v, ...) __VA_ARGS__. Почему?
[ZX]