Зачем в современных проектах все еще используются макросы?
Макросы нужны там где нужно во время компиляции программы генерировать код. Функции или даже шаблоны для этого не подходят.
Например вы хотите логгер, который бы писал в каком файле, и на какой строке произошла ошибка, вы пишите код cout << __FILE__ << __LINE__ << "error message";
И все хорошо пока вы его вставляете руками туда куда нужно. Но вот вы решили что это некрасиво, и планируете вынести код в функцию. Однако - план проваливается, так как теперь код пишет каждый раз один и тот же файл, и одну и ту же строку - ту самую в которой код удобно расположился в вашей функции. Выходов два:
 - каждый раз дублировать этот код
 - использовать макросы
Итак теперь вы тяжело вздохнув, и закрыв портретик Страуструпа шторкой ( чтобы не видел как вы предаетесь адскому макросостроению ) пишите макрос#define LOG(x) std::cout << __FILE__ << __LINE__ << x << std::endl;
Теперь где угодно можно писать
LOG("this is error number " << errno);
и все будет работать как и было запланировано.
Еще из полезных свойств макросов - улучшать чужой плохой код. Если у вас есть много переменных, или переменных имена у которых почти совпадают с именами функций и вам нужно сделать этот код умнее, вы пользуетесь макросами, склеиваете строки через ## или преобразовываете переменную в строку через #
Это довольно мощные инструменты ( пусть до лисповских максросов им далеко ) которые реально позволяют улучшить код и/или избежать кучу повторений одного и того же блока кода.
я не использую