Только вот написал парсер строки формата (printf) времени компиляции. Который позволяет написать fprintf(file, "%d %s %f...", a, b, c...) И оно всё разворачивается (или сообщает об ошибке, если аргументы не соответствуют формату) в линейный код, когда в файл тупо пишется a, пишется b, пишется c, без каких-то разборов строки формата в рантайме (её вообще в рантайме нет). Идею изначально почерпнул у
https://www.zverovich.net/ (см. всё по фразе "format", достаточно интересно, в частности
https://github.com …r/include/fmt/format.h). Но у там есть такой FMT_STRING(...) который является краеугольным камнем: протащить строку формата во время компиляции можно только в пространстве constexpr или в пространстве типов, но фактически только в пространстве типов, т.к. constexpr не позволит одновременно протаскивать в функцию constexpr (формат) и явно не-constexpr (аргументы для печати). A объявить новый тип в середине выражения можно только внутри лямбды. От макроса с лямбдой можно избавиться, если вспомнить об user defined literals (увы, с микрософт-студией в пролёте до как минимум следующего года, clang, gcc -- ok), способного возвратить шаблонный тип (
https://habr.com/ru/post/243581/). В конечном счёте, если нужен ровно тот же синтаксис, придётся макрос оставить но попроще: #define fprintf(FILE, FMT, ...) fprintf(FILE, FMT##_f, ##__VA_ARGS__).