У меня есть такой код:
const std::string first = "|>first {} thing<|";
const std::string second = "|>second thing<|";
const std::string third = "|>third thing<|";
const std::string fourth = "|>fourth thing<|";
const std::string out = std::format("Testing {} format {} string {}", first, second, third, fourth);
std::cout << out << std::endl;
Этот код выводит следующее:
Testing |>first {} thing<| format |>second thing<| string |>third thing<|
Я хотел бы, чтобы код выводил:
Testing |>first |>second thing<| thing<| format |>third thing<| string |>fourth thing<|
Разница в том, что |>first {} thing<| заменен на |>first |>second thing<| thing<|. То есть формат применяется рекурсивно. std::format имеет множество проверок во время компиляции, но теоретически ничто не мешает std::vformat применять рекурсивно.
Прежде чем реализовать эту функциональность самостоятельно, я хотел бы знать, существует ли она в стандартной библиотеке или уже доступно другое надежное решение.
Пример из реального мира:
У меня есть пять (на самом деле около 40) разных запросов, каждый из которых требует data1, data2, data3, ... просто в другом месте. Данные будут известны во время выполнения, но позиция будет известна во время компиляции. У меня есть возможность выбрать пять разных классов запросов или один шаблон с разными специализациями: using Query1 = BasicQuery("BLAH {} BLAH");using Query2 = BasicQuery("BLAH BLAH {}"); и так далее. Это может быть разница как в 1500 строках кода, так и в ~250, а также в более приятном интерфейсе вызова по сравнению с запутанным (одна функция выполнения для каждого класса или функция для каждого запроса, если я решил иметь только один класс со всеми запросами).
Кроме того, добавление функции для каждого запроса — не вариант. Каждый запрос имеет разный тип возвращаемого значения (и даже разное количество возвратов) в зависимости от характера запроса. Класс также обрабатывает анализ возвращаемых данных на основе типа возвращаемого значения и количества возвратов. Специализации шаблонов — действительно хорошее решение этой проблемы. Я надеюсь, что смогу также использовать специализации для самой строки запроса.
@n.m.couldbeanAI Например, если у вас есть пять разных запросов, каждый из которых нужно data1, data2, data3, ... просто в другом месте. Данные будут известны во время выполнения, а позиция во время компиляции, тогда у вас будет возможность выбрать пять разных запросов (класс или функция) или один шаблон с разными специализациями: using Query1 = BasicQuery("BLAH {} BLAH"); using Query2 = BasicQuery("BLAH BLAH {}"); и так далее. Это может быть разница как в 1500 строках кода, так и в ~250, а также в более приятном интерфейсе вызова по сравнению со сложным (одна функция execute на класс или функция на запрос).
Я не понимаю этого предложения: «...но теоретически ничто не мешает std::vformat сделать это». сделать что? применять проверки времени компиляции?
Не могли бы вы отредактировать свой вопрос, указав в комментариях реальный пример? (Хотя я не вижу, насколько здесь полезно поведение вложенности.) В противном случае мы могли бы предложить что-то недостаточно общее.
@463035818_is_not_an_ai std::format проверяет строку формата во время компиляции. Возможно, одна из рекурсивных строк неизвестна до времени выполнения. Поэтому std::format не может это проверить. std::vformat существует как полностью динамический вариант std::format. Под «сделать это» я имею в виду рекурсивное функционирование, поскольку знание времени компиляции не имеет значения для std::vformat.
@Botje, я обновил это
честно говоря, описание вашего варианта использования расплывчато. Не сосредотачивайтесь только на том, что вы считаете решением, а давайте пойдем по этому пути с самого начала. Это проблема xy вы убеждены, что y решает x, но нам все еще не хватает полного понимания x. Попробуйте создать минимально воспроизводимый пример. Вам не обязательно показывать 40 различных запросов, даже не 5, но на самом деле показ кода для 2 очень поможет.
@ 463035818_is_not_an_ai Понятно, я сделаю прототип чего-нибудь в компилируемом проводнике. Дайте мне несколько минут, пожалуйста.
это общий симптом вопросов, направленных на то, чтобы избежать написания кода. Вы не показываете нам код, написания которого хотите избежать. Теперь представьте, что кто-то знает, как решить проблему, не написав код, которого вы хотите избежать. Для него не будет очевидно, о каком коде вы говорите, потому что он не стал бы его писать.
Судя по вашему описанию, я думаю, что было бы намного лучше использовать замену на основе словаря для индексации элементов, как в Pythonish "{a} {b}".format(a=1, b=1). И почему бы и нет BasicQuery("BLAH {} BLAH", "data");. Обратите внимание, что вы задаете вопрос XY. Вы специально спрашиваете о существовании рекурсии std::format, а не о том, как писать чистый код с использованием шаблонных запросов или чего-то подобного. Кроме того, очень сложно ответить, существует ли что-то в мире или нет — никто из моих знакомых не обладает такой силой.
Используйте литералы с фиксированными строками и помещайте в тип строку формата. Затем просто введите «стереть».





Существует ли «рекурсивный» формат std::format?
Нет, нет. Вам придется написать его самостоятельно.
У меня есть возможность выбрать пять разных классов запросов или один шаблонный.
Рассмотрите возможность использования шаблонизатора.
Мой 1-минутный поиск https://www.google.com/search?q=C%2B%2B+templating+engine привел к Есть ли хороший шаблонизатор для C++ , https:/ /jinja2cpp.github.io/ и https://github.com/pantor/inja .
Какой кошмар функциональности. Зачем это кому-то нужно?