Под Хабракатом небольшой этюд позволяющий писать маленькие или большие приложения, которые содержат в себе свой же код и выглядят при этом почти адекватно.
Как видно из исходника, явно списать код нужно только из «шапки», потому что все что находится в REPEAT-блоке будет автоматически застринговано и сохранено.
Сам макрос REPEAT устроен следующим образом: он принимает переменное число аргументов (чтоб не боятся запятых), затем «стрингует» то что ему передали, а затем еще раз повторяет то что ему передали, но на этот раз без кавычек (чтоб сохранить функционал).
Вот что получается после препроцессинга:
Признаться честно, я код изменил и привел в читаемый вид, потому что препроцессор почти все лепит в одну строчку. Тем не менее кроме переносов и лишних кавычек все на своих местах.
После запуска в stdout будет выведен функционально-идентичный исходник. Оформление только слегка помнется.
PS #include можно внести в REPEAT-блок, тогда его можно будет не писать явно в строке.
#include <stdio.h> #define REPEAT(...) #__VA_ARGS__;__VA_ARGS__ char * ref = REPEAT( int main() { printf("#include <stdio.h>\n" "#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__\n" "char * ref = REPEAT(%s)", ref); return 0; } )
Как видно из исходника, явно списать код нужно только из «шапки», потому что все что находится в REPEAT-блоке будет автоматически застринговано и сохранено.
Сам макрос REPEAT устроен следующим образом: он принимает переменное число аргументов (чтоб не боятся запятых), затем «стрингует» то что ему передали, а затем еще раз повторяет то что ему передали, но на этот раз без кавычек (чтоб сохранить функционал).
Вот что получается после препроцессинга:
g++ -E main.cpp
char * ref = "int main()" "{" " printf(\"#include <stdio.h>\\n\"" " \"#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__\\n\"" " \"char * ref = REPEAT(%s)\", ref);" " return 0;" "}"; int main() { printf("#include <stdio.h>\n" "#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__\n" "char * ref = REPEAT(%s)", ref); return 0; }
Признаться честно, я код изменил и привел в читаемый вид, потому что препроцессор почти все лепит в одну строчку. Тем не менее кроме переносов и лишних кавычек все на своих местах.
После запуска в stdout будет выведен функционально-идентичный исходник. Оформление только слегка помнется.
PS #include можно внести в REPEAT-блок, тогда его можно будет не писать явно в строке.
