diff --git a/bench/process_result.cpp b/bench/process_result.cpp index 8e57c51..d427a75 100644 --- a/bench/process_result.cpp +++ b/bench/process_result.cpp @@ -13,8 +13,10 @@ using results_vector = std::vector; bool extract_cpu_info(ssa text, ssa& res) { // Найдём, где начинается "Run on ", потом где за ним начинается "\n---" + // Find where "Run on" begins, then where after it "\n---" begins size_t start = text.find("Run on "), end = text.find("\n---", start); // Если что-то не нашлось - ошибка + // If something was not found - an error if (start == str::npos || end == str::npos) { return false; } @@ -34,6 +36,7 @@ struct result_info { throw std::runtime_error{"Not found cpu info"}; } // Текущее положение поставим сразу за cpuinfo и откинем завершающие переводы строк + // We will put the current position immediately after cpuinfo and discard the final line feeds current_text_ = current_text_(cpu_info_.end() - current_text_.begin() + 1).trimmed_right("\n"); } }; @@ -57,14 +60,16 @@ stringa get_file_content(stra filePath) { std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); // Такой тип удобен для передачи потом в stringa + // This type is convenient for later passing to stringa lstringsa<0> result; file.read(result.set_size(size), size); result.replace("\r\n", "\n"); - return result; + return std::move(result); } results_vector get_results_infos() { // Отберём в директории results все файлы с названиями, заканчивающимися на ".txt" и отсортируем их по имени + // Select all files in the results directory with names ending in ".txt" and sort them by name const ssa suffix = ".txt", dirForResults = "results/"; std::vector fileNames; for (const auto& f: std::filesystem::directory_iterator{str_to_path(dirForResults)}) { @@ -88,6 +93,7 @@ results_vector get_results_infos() { for (const auto& f : fileNames) { ssa fileName = f; // В начале имени файла может идти число и дефис, для сортировки, уберём их + // At the beginning of the file name there can be a number and a hyphen, for sorting, remove them if (auto delimeter = fileName.find('-'); delimeter != str::npos && delimeter > 0) { if (std::get<1>(fileName(0, delimeter).to_int()) == IntConvertResult::Success) { fileName.remove_prefix(delimeter + 1); @@ -188,6 +194,7 @@ ssa extract_source_for_benchmark(ssa benchName, ssa sourceText) { auto [it, not_exist] = textes.try_emplace(benchName); if (not_exist) { // Ищем имя функции для этого бенчмарка + // Looking for the name of the function for this benchmark size_t start = sourceText.find(lstringa<128>{"->Name(\"" + e_repl(benchName, "\"", "\\\"") + "\")"}); if (start == str::npos) { std::cerr << "Can not found benchmark function name for " << benchName << std::endl; @@ -204,6 +211,7 @@ ssa extract_source_for_benchmark(ssa benchName, ssa sourceText) { auto [func_it, not_exist] = textes.try_emplace(funcName); if (not_exist) { // Теперь ищем саму эту функцию + // Now we look for this function itself start = sourceText.find(lstringa<128>{funcName + "(benchmark::State"}); if (start == str::npos) { std::cerr << "Can not found source function " << funcName << " for benchmark " << benchName << std::endl; @@ -218,6 +226,7 @@ ssa extract_source_for_benchmark(ssa benchName, ssa sourceText) { } size_t end = -1; // Проверим, возможно там есть переход на другую функцию через //> + // Let's check, maybe there is a transition to another function via //> ssa prevLine = sourceText.from_to(sourceText.find_last('\n', start - 1) + 1, start); if (prevLine.starts_with("//> ")) { prevLine.remove_prefix(4); @@ -262,6 +271,7 @@ void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, auto source = extract_source_for_benchmark(benchName, sourceText); auto comment = extract_comment(commentsText, benchName); // Нужно вывести название бенча и коммент + // Need to display title and comment out += "\n" + repl_html_symbols(benchName) + "" + @@ -296,11 +306,13 @@ void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, continue; } else if (line.starts_with("--") && !line.ends_with("---")) { // Начинается новый набор бенчмарков + // Starts a new set of benchmarks if (needFooter) { write_benchset_footer(out, script_text); } benchName = extract_name_result(line, result); // Из названия набора надо удалить начальные и конечные --- + // From the name of the set we need to remove the beginning and end --- benchName = benchName.from_to(benchName.find(' ') + 1, benchName.find_last(' ')).trimmed(); write_benchset_header(out, results, benchName, ++benchSetId); needFooter = true; @@ -308,6 +320,7 @@ void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, script_text = "bench_sets['" + e_repl(benchName.to_str(), "'", "\\'") + "'] = {id:'bs" + benchSetId +"', tests:["; } // Эти строки надо пропустить во всех файлах + // These lines must be skipped in all files for (unsigned idx = 1; idx < results.size(); idx++) { if (splitters[idx].is_done()) { std::cerr << "Not expected end of file for " << results[idx].platform_ << std::endl; diff --git a/include/simstr/sstring.h b/include/simstr/sstring.h index abb488b..583f66a 100644 --- a/include/simstr/sstring.h +++ b/include/simstr/sstring.h @@ -4618,8 +4618,8 @@ struct expr_num { }; /*! - * @brief Оператор конкатенации для строкового выражения и целого числа. * @ingroup StrExprs + * @brief Оператор конкатенации для строкового выражения и целого числа. * @param a - строковое выражение * @param s - число * @details Число конвертируется в десятичное строковое представление. @@ -4630,8 +4630,8 @@ inline constexpr auto operator + (const A& a, T s) { } /*! - * @brief Оператор конкатенации для целого числа и строкового выражения. * @ingroup StrExprs + * @brief Оператор конкатенации для целого числа и строкового выражения. * @param s - число * @param a - строковое выражение * @details Число конвертируется в десятичное строковое представление. @@ -4642,8 +4642,8 @@ inline constexpr auto operator + (T s, const A& a) { } /*! - * @brief Преобразование целого числа в строковое выражение * @ingroup StrExprs + * @brief Преобразование целого числа в строковое выражение * @tparam K - тип символов * @tparam T - тип числа, выводится из аргумента * @param t - число @@ -4690,8 +4690,8 @@ struct expr_real { }; /*! - * @brief Оператор конкатенации для строкового выражения и вещественного числа (`float`, `double`). * @ingroup StrExprs + * @brief Оператор конкатенации для строкового выражения и вещественного числа (`float`, `double`). * @param a - строковое выражение * @param s - число * @details Число конвертируется в строковое представление через sprintf("%.16g"). @@ -4703,8 +4703,8 @@ inline constexpr auto operator+(const A& a, R s) { } /*! - * @brief Оператор конкатенации для вещественного числа (`float`, `double`) и строкового выражения. * @ingroup StrExprs + * @brief Оператор конкатенации для вещественного числа (`float`, `double`) и строкового выражения. * @param s - число * @param a - строковое выражение * @details Число конвертируется в строковое представление через `sprintf("%.16g")`. @@ -4716,8 +4716,8 @@ inline constexpr auto operator+(R s, const A& a) { } /*! - * @brief Преобразование `double` числа в строковое выражение * @ingroup StrExprs + * @brief Преобразование `double` числа в строковое выражение * @param t - число * @details Возвращает строковое выражение, которое генерирует десятичное представление заданного числа * с помощью `sprintf("%.16g")`. Может использоваться, когда надо конкатенировть число и строковый литерал @@ -4780,8 +4780,8 @@ struct expr_join { }; /*! - * @brief Получить строковое выражение, конкатенирующее строки в контейнере в одну строку с заданным разделителем * @ingroup StrExprs + * @brief Получить строковое выражение, конкатенирующее строки в контейнере в одну строку с заданным разделителем * @tparam tail - добавлять ли разделитель после последней строки * @tparam skip_empty - пропускать пустые строки без добавления разделителя * @param s - контейнер со строками, должен поддерживать `range for`. @@ -4863,8 +4863,8 @@ struct expr_replaces { }; /*! - * @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки * @ingroup StrExprs + * @brief Получить строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки * @tparam K - тип символа, выводится из первого аргумента * @param w - начальная строка * @param p - строковый литерал, искомая подстрока @@ -4877,8 +4877,8 @@ inline constexpr auto e_repl(simple_str w, T&& p, X&& r) { } /*! - * @brief Строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. * @ingroup StrExprs + * @brief Строковое выражение, генерирующее строку с заменой всех вхождений заданной подстроки. * @tparam K - тип строкиs * @details `e_repl` позволяет заменять только с использование строковых литералов. * В случае, когда искомая подстрока или строка замены не известны при компиляции, и задаются в runtime, @@ -4972,8 +4972,8 @@ template<> struct replace_search_result_store : std::vector> {}; /*! - * @brief Тип для строкового выражения, генерирующее строку, в которой заданные символы заменяются на заданные строки. * @ingroup StrExprs + * @brief Тип для строкового выражения, генерирующее строку, в которой заданные символы заменяются на заданные строки. * @tparam K - тип символа * @tparam UseVectorForReplace - использовать вектор для запоминания результатов поиска вхождений символов * @details Этот тип применяется, когда состав символов или соответствующих им замен не известен в compile time, @@ -5359,9 +5359,9 @@ protected: }; /*! + * @ingroup StrExprs * @brief Возвращает строковое выражение, генерирующее строку, в которой заданные символы * заменены на заданные подстроки. - * @ingroup StrExprs * @tparam UseVector - использовать вектор для сохранения результатов поиска символов. * Более подробно описано в `expr_replace_symbols`. * @param src - исходная строка diff --git a/include/simstr/strexpr.h b/include/simstr/strexpr.h index 678a4fc..6de9977 100644 --- a/include/simstr/strexpr.h +++ b/include/simstr/strexpr.h @@ -1,7 +1,9 @@ /* + * ver. 1.2.4 * (c) Проект "SimStr", Александр Орефков orefkov@gmail.com - * ver. 1.0 * База для строковых конкатенаций через выражения времени компиляции + * (c) Project "SimStr", Alexander Orefkov orefkov@gmail.com + * Base for string concatenations via compile-time expressions */ #pragma once #include @@ -18,6 +20,7 @@ namespace simstr { // Выводим типы для 16 и 32 битных символов в зависимости от размера wchar_t +// Infer types for 16 and 32 bit characters depending on the size of wchar_t inline constexpr bool wchar_is_u16 = sizeof(wchar_t) == 2; using wchar_type = std::conditional::type; @@ -92,10 +95,33 @@ void func(T&& lit); Тогда компилятор будет подставлять для T точный тип параметра без попыток привести тип к другому типу, и выражение с параметром char[100] - не скомпилируется. + +Helper templates for defining string literals. +They are used to limit types in function parameters strictly as `const K(&)[N]` +If we write +template +void func(const char(&lit)[N]); +then it will be possible to pass a non-constant buffer to such a function, which may cause an error: + +// Allocate space for symbols +char buf[100]; +// Somehow the buffer was filled, say, to half. + +stringa text = buf; +Here the compiler will convert buf from type char[100] to type const char[100] and call the constructor +for a string literal, text will simply contain a pointer to buf and length 100. + +Therefore, we declare such parameters as +template::symb_type, size_t N = const_lit::Count> +void func(T&& lit); + +Then the compiler will substitute for T the exact type of the parameter without attempting to cast the type to another type, +and an expression with the char[100] parameter will not compile. */ -template struct const_lit; // sfinae отработает, так как не найдёт определения +template struct const_lit; // sfinae отработает, так как не найдёт определения | sfinae will work because it won't find a definition // Для правильных типов параметров есть определение, в виде специализации шаблона +// There is a definition for the correct parameter types, in the form of a template specialization template requires(is_one_of_char_v) struct const_lit { @@ -104,6 +130,7 @@ struct const_lit { }; // Тут ещё дополнительно ограничиваем тип литерала +// Here we further restrict the type of the literal template struct const_lit_for; template @@ -174,9 +201,9 @@ concept StrType = requires(const A& a) { } && std::is_same_v::symb_type, K>; /*! - * @brief Строковые выражения * @defgroup StrExprs Строковые выражения - * @details Все типы владеющих строк могут инициализироваться с помощью "строковых выражений" + * @ru @brief Строковые выражения + * @ru @details Все типы владеющих строк могут инициализироваться с помощью "строковых выражений" * (по сути это вариант https://en.wikipedia.org/wiki/Expression_templates для строк). * Строковое выражение - это объект произвольного типа, у которого имеются методы: * - `size_t length() const`: выдает длину строки @@ -203,20 +230,20 @@ concept StrType = requires(const A& a) { * stringa text = header + ", count = " + count + ", done"; * ``` * Существует несколько типов строковых выражений "из коробки", для выполнения различных операций со строками - * - `expr_spaces<ТипСимвола, КоличествоСимволов, Символ>{}`: выдает строку длиной КоличествоСимволов, + * - `expr_spaces< ТипСимвола, КоличествоСимволов, Символ>{}`: выдает строку длиной КоличествоСимволов, * заполненную заданным символом. Количество символов и символ - константы времени компиляции. * Для некоторых случаев есть сокращенная запись: - * - `e_spca<КоличествоСимволов>()`: строка char пробелов - * - `e_spcw<КоличествоСимволов>()`: строка w_char пробелов - * - `expr_pad<ТипСимвола>{КоличествоСимволов, Символ}`: выдает строку длинной КоличествоСимволов, + * - `e_spca< КоличествоСимволов>()`: строка char пробелов + * - `e_spcw< КоличествоСимволов>()`: строка w_char пробелов + * - `expr_pad< ТипСимвола>{КоличествоСимволов, Символ}`: выдает строку длинной КоличествоСимволов, * заполненную заданным символом. Количество символов и символ могут задаваться в рантайме. - * Сокращенная запись: `e_c(КоличествоСимволов, Символ)` - * - `e_choice(bool Condition, StrExpr1, StrExpr2)`: если Condition == true, результат будет равен StrExpr1, иначе StrExpr2 - * - `e_num<ТипСимвола>(ЦелоеЧисло)`: конвертирует число в десятичное представление. Редко используется, так как + * Сокращенная запись: `e_c (КоличествоСимволов, Символ)` + * - `e_choice (bool Condition, StrExpr1, StrExpr2)`: если Condition == true, результат будет равен StrExpr1, иначе StrExpr2 + * - `e_num< ТипСимвола>(ЦелоеЧисло)`: конвертирует число в десятичное представление. Редко используется, так как * для строковых выражений и чисел переопределен оператор "+", и число можно просто написать как text + number; - * - `e_real<ТипСимвола>(ВещественноеЧисло)`: конвертирует число в десятичное представление. Редко используется, так как + * - `e_real< ТипСимвола>(ВещественноеЧисло)`: конвертирует число в десятичное представление. Редко используется, так как * для строковых выражений и чисел переопределен оператор "+", и число можно просто написать как `text + number`; - * - `e_join(контейнер, "Разделитель")`: конкатенирует все строки + * - `e_join< bool ПослеПоследнего = false, bool ПропускатьПустые = false>(контейнер, "Разделитель")`: конкатенирует все строки * в контейнере, используя разделитель. * Если `ПослеПоследнего == true`, то разделитель добавляется и после последнего элемента контейнера, иначе только * между элементами. @@ -224,16 +251,70 @@ concept StrType = requires(const A& a) { * тоже вставляется разделитель * - `e_repl(ИсходнаяСтрока, "Искать", "Заменять")`: заменяет в исходной строке вхождения "Искать" на "Заменять". * Шаблоны поиска и замены - строковые литералы времени компиляции. - * - `expr_replaced<ТипСимвола>{ИсходнаяСтрока, Искать, Заменять}`: заменяет в исходной строке вхождения Искать на Заменять. + * - `expr_replaced< ТипСимвола>{ИсходнаяСтрока, Искать, Заменять}`: заменяет в исходной строке вхождения Искать на Заменять. * Шаблоны поиска и замены - могут быть любыми строковыми объектами в рантайме. - * * и т.д. и т.п. + * + * @en @brief Строковые выражения + * @en @detailsAll owning string types can be initialized using "string expressions" + * (essentially a variant of https://en.wikipedia.org/wiki/Expression_templates for strings). + * A string expression is an object of an arbitrary type that has methods: + * - `size_t length() const`: returns the length of the string + * - `K* place(K*) const`: copy the characters of the string to the intended buffer and return a pointer behind the last character + * - `typename symb_type`: shows what type of symbols it works with. + * + * During initialization, a string object asks the string expression for its size, allocates the necessary memory, + * and passes the memory to a string expression that places the characters in the allocated buffer. + * + * All library string objects are themselves string expressions that simply copy the original string. + * Basically, string expressions are used to concatenate or convert strings. + * + * For all string expressions, @ref op_plus_str_expr "operator +" is defined, which creates a new string expression from two operands + * simstr::strexprjoin, which combines two string expressions, and which in the `length` method returns the sum of the `length` original operands, + * and in the `place` method - places first the first operand, then the second, into the result buffer. + * And since this operator itself returns a string expression, you can again apply `operator +` to it, forming a chain of several + * string expressions, and eventually “materialize” the last resulting object, which will first calculate the size of the entire shared memory + * for the final result, and then will place the nested subexpressions into a single buffer. + * + * Also `operator +` is defined for string expressions and string literals, string expressions and numbers + * (numbers are converted to decimal representation), and you can also add the desired types of string expressions yourself. + * Example: + * ```cpp + * stringa text = header + ", count = " + count + ", done"; + * ``` + * There are several types of string expressions out of the box to perform various operations on strings + * - `expr_spaces< Character Type, Number of Characters, Symbol>{}`: returns a string of length Number of Characters, + * filled with the specified character. The number of characters and character are compile-time constants. + * For some cases there is a shorthand notation: + * - `e_spca< Number of Characters>()`: char string of spaces + * - `e_spcw< Number of Characters>()`: w_char string of spaces + * - `expr_pad< Character Type>{Number of Characters, Symbol}`: produces a string long Number of Characters, + * filled with the specified character. The number of characters and the symbol can be set at runtime. + * Shorthand: `e_c(Number of Characters, Character)` + * - `e_choice(bool Condition, StrExpr1, StrExpr2)`: if Condition == true, the result will be StrExpr1, otherwise StrExpr2 + * - `e_num< CharacterType>(IntegerNumber)`: Converts a number to decimal notation. Rarely used because + * for string expressions and numbers the "+" operator is redefined, and the number can simply be written as text + number; + * - `e_real< CharacterType>(RealNumber)`: Converts a number to decimal notation. Rarely used because + * for string expressions and numbers the "+" operator is overridden, and the number can simply be written as `text + number`; + * - `e_join< bool AfterLast = false, bool SkipEmpty = false>(container, "Separator")`: concatenates all strings + * in a container using a separator. + * If `AfterLast == true`, then the separator is added after the last element of the container, otherwise only + * between elements. + * If `Skip Empty == true`, then empty lines do not add a separator, otherwise for each empty line + * a separator is also inserted + * - `e_repl(SourceString, "Search", "Replace")`: replaces occurrences of "Search" with "Replace" in the source string. + * Find and replace patterns are compile-time string literals. + * - `expr_replaced< CharacterType>{SourceString, Search, Replace}`: replaces occurrences of Search with Replace in the source string. + * Search and replace patterns - can be any string objects at runtime. + * etc. etc. */ /*! - * @brief Концепт "Строковых выражений" * @ingroup StrExprs - * @details Это концепт, проверяющий, является ли тип "строковым выражением". + * @ru @brief Концепт "Строковых выражений" + * @ru @details Это концепт, проверяющий, является ли тип "строковым выражением". + * @en @brief Concept of "String Expressions" + * @en @details This is a concept that checks whether a type is a "string expression". */ template concept StrExpr = requires(const A& a) { @@ -243,32 +324,49 @@ concept StrExpr = requires(const A& a) { }; /*! - * @brief Концепт строкового выражения заданного типа символов * @ingroup StrExprs - * @tparam A - проверяемый тип - * @tparam K - проверяемый тип символов - * @details Служит для задания ограничения к строковому выражению по типу символов + * @ru @brief Концепт строкового выражения заданного типа символов + * @ru @tparam A - проверяемый тип + * @ru @tparam K - проверяемый тип символов + * @ru @details Служит для задания ограничения к строковому выражению по типу символов + * @en @brief The concept of a string expression of a given character type + * @en @tparam A - type being checked + * @en @tparam K - character type to be checked + * @en @details Used to set restrictions on a string expression by character type */ template concept StrExprForType = StrExpr && std::is_same_v; /* -* Шаблонные классы для создания строковых выражений из нескольких источников +* Шаблонные классы для создания строковых выражений из нескольких источников. * Благодаря компиляторно-шаблонной "магии" позволяют максимально эффективно * получать результирующую строку - сначала вычисляется длина результирующей строки, * потом один раз выделяется память для результата, после символы помещаются в * выделенную память. * Для конкатенация двух объектов строковых выражений в один + +* Template classes for creating string expressions from multiple sources. +* Thanks to compiler-template "magic" they allow you to maximize efficiency +* get the resulting string - first the length of the resulting string is calculated, +* then memory is allocated once for the result, after which the characters are placed in +* allocated memory. +* For concatenating two string expression objects into one. */ /*! - * @brief Шаблонный класс для конкатенации двух строковых выражений в одно с помощью `operator +` * @ingroup StrExprs - * @tparam A - Тип первого операнда - * @tparam B - Тип второго операнда - * @details Этот объект запоминает ссылки на два операнда операции сложения. + * @ru @brief Шаблонный класс для конкатенации двух строковых выражений в одно с помощью `operator +` + * @ru @tparam A - Тип первого операнда + * @ru @tparam B - Тип второго операнда + * @ru @details Этот объект запоминает ссылки на два операнда операции сложения. * Когда у него запрашивают необходимый для результата размер буфера - он выдает сумму длин своих операндов. * Когда запрашивают размещение символов в буфере - размещает сначала первый операнд, затем второй. + * @en @brief Template class for concatenating two string expressions into one using `operator +` + * @en @tparam A - Type of first operand + * @en @tparam B - Type of second operand + * @en @detailsThis object remembers references to the two operands of the addition operation. + * When asked for the required buffer size for a result, it gives the sum of the lengths of its operands. + * When asked to place characters in a buffer, place the first operand first, then the second. */ template B> struct strexprjoin { @@ -290,17 +388,27 @@ struct strexprjoin { }; /*! - * @brief Оператор сложения двух произвольных строковых выражения для одинакового типа символов * @ingroup StrExprs * @anchor op_plus_str_expr - * @param a - первое строковое выражение - * @param b - второе строковое выражение - * @return strexprjoin, строковое выражение, генерирующее объединение переданных выражений - * @details Когда складываются два объекта - строковых выражения, один типа `A`, другой типа `B`, + * @ru @brief Оператор сложения двух произвольных строковых выражения для одинакового типа символов. + * @ru @param a - первое строковое выражение. + * @ru @param b - второе строковое выражение. + * @ru @return strexprjoin, строковое выражение, генерирующее объединение переданных выражений. + * @ru @details Когда складываются два объекта - строковых выражения, один типа `A`, другой типа `B`, * мы возвращаем объект типа strexprjoin, который содержит ссылки на два этих операнда. * А сам объект strexprjoin тоже в свою очередь является строковым выражением, и может участвовать * в следующих операциях сложения. Таким образом формируется "дерево" из исходных строковых * выражений, которое потом за один вызов "материализуется" в конечный результат. + * + * @en @brief An addition operator for two arbitrary string expressions of the same character type. + * @en @param a - first string expression + * @en @param b - second string expression + * @en @return strexprjoin, a string expression that generates a join of the given expressions. + * @en @details When two objects are added - string expressions, one of type `A`, the other of type `B`, + * we return an object of type strexprjoin, which contains references to these two operands. + * And the strexprjoin object itself, in turn, is also a string expression, and can participate + * in the following addition operations. In this way, a “tree” is formed from the original strings + * expressions, which are then “materialized” into the final result in one call. */ template B> inline auto operator+(const A& a, const B& b) { @@ -308,15 +416,24 @@ inline auto operator+(const A& a, const B& b) { } /*! - * @brief Конкатенация ссылки на строковое выражение и значения строкового выражения * @ingroup StrExprs - * @tparam A - Тип одного строкового выражения - * @tparam B - Тип другого строкового выражения - * @tparam last - какое из них первое - * @details Чтобы иметь возможность складывать строковое выражение с операндами, не являющимися строковым выражением, + * @ru @brief Конкатенация ссылки на строковое выражение и значения строкового выражения. + * @ru @tparam A - Тип одного строкового выражения. + * @ru @tparam B - Тип другого строкового выражения. + * @ru @tparam last - какое из них первое. + * @ru @details Чтобы иметь возможность складывать строковое выражение с операндами, не являющимися строковым выражением, * нам нужно иметь возможность вернуть из `operator+` объект, который сохранит ссылку на операнд, являющийся строковым * выражением, а для не строкового операнда будет иметь поле со строковым выражением, обрабатывающим второй операнд. * Можно посмотреть пример в simstr::operator+() + * + * @en @brief Concatenation of a reference to a string expression and the value of the string expression. + * @en @tparam A - Type of a single string expression. + * @en @tparam B - Type of another string expression. + * @en @tparam last - which one is the first. + * @en @details To be able to add a string expression with non-string operands, + * we need to be able to return an object from `operator+` that will retain a reference to the operand, which is a string + * expression, and for a non-string operand will have a field with a string expression that processes the second operand. + * You can see an example in simstr::operator+() */ template B, bool last = true> struct strexprjoin_c { @@ -350,10 +467,10 @@ template struct is_one_of_type : std::false_type {}; /*! - * @brief "Пустое" строковое выражение * @ingroup StrExprs - * @tparam K - тип символа - * @details Простое строковое выражение, генерирующее пустую строку. + * @ru @brief "Пустое" строковое выражение. + * @ru @tparam K - тип символа. + * @ru @details Простое строковое выражение, генерирующее пустую строку. * В основном применяется в функции e_choice, когда одна из веток должна вернуть пустую строку. * Либо для начала операции сложения строковых выражений, когда другой операнд не является строковым выражением, * но для него есть оператор сложения со строковыми выражениями. @@ -363,7 +480,20 @@ struct is_one_of_type : std::false_type {}; * - eeu для пустой строки char16_t * - eeuu для пустой строки char32_t * - * Пример: + * @en @brief An "empty" string expression. + * @en @tparam K is a symbol. + * @en @details A simple string expression that generates an empty string. + * Mainly used in the e_choice function when one of the branches should return an empty string. + * Either to start the addition operation of string expressions when the other operand is not a string expression, + * but there is an addition operator for it with string expressions. + * For convenience, constant objects of this type have already been defined for different types of symbols: + * - eea for empty char string + * - eew for empty string wchar_t + * - eeu for empty string char16_t + * - eeuu for empty string char32_t + * + * + * @ru Пример: @en Example: @~ * ```cpp * result = shost + e_choice(sserv.is_empty(), eea, ":" + sserv); * ``` @@ -384,23 +514,27 @@ struct empty_expr { }; /*! - * @brief Пустое строковое выражение типа char * @ingroup StrExprs + * @ru @brief Пустое строковое выражение типа char. + * @en @brief Empty string expression of type char. */ inline constexpr empty_expr eea{}; /*! - * @brief Пустое строковое выражение типа wchar_t * @ingroup StrExprs + * @ru @brief Пустое строковое выражение типа wchar_t. + * @en @brief Empty string expression of type wchar_t. */ inline constexpr empty_expr eew{}; /*! - * @brief Пустое строковое выражение типа char16_t * @ingroup StrExprs + * @ru @brief Пустое строковое выражение типа char16_t. + * @en @brief Empty string expression of type char16_t. */ inline constexpr empty_expr eeu{}; /*! - * @brief Пустое строковое выражение типа char32_t * @ingroup StrExprs + * @ru @brief Пустое строковое выражение типа char32_t. + * @en @brief Empty string expression of type char32_t. */ inline constexpr empty_expr eeuu{}; @@ -419,10 +553,13 @@ struct expr_char { }; /*! - * @brief Оператор сложения строкового выражения и одного символа * @ingroup StrExprs - * @return строковое выражение, объединяющее переданное выражение и символ - * @details Пример: + * @ru @brief Оператор сложения строкового выражения и одного символа. + * @ru @return строковое выражение, объединяющее переданное выражение и символ. + * @en @brief Addition operator of a string expression and one character. + * @en @return a string expression that combines the passed expression and a character. + * @details @ru Пример: @en Example: @~ + * @~ * ```cpp * reply = prompt + '>' + result; * ``` @@ -433,10 +570,14 @@ constexpr inline auto operator+(const A& a, K s) { } /*! - * @brief Генерирует строку из 1 заданного символа * @ingroup StrExprs - * @param S - символ - * @return строковое выражение для строки из одного символа + * @ru @brief Генерирует строку из 1 заданного символа. + * @ru @param s - символ. + * @ru @return строковое выражение для строки из одного символа. + * + * @en @brief Generates a string of 1 given character. + * @en @param s - symbol. + * @en @return string expression for a single character string. */ template constexpr inline auto e_char(K s) { @@ -458,9 +599,9 @@ struct expr_literal { }; /*! - * @brief Преобразует строковый литерал в строковое выражение. * @ingroup StrExprs - * @details Строковые литералы сами по себе не являются строковыми выражениями. + * @ru @brief Преобразует строковый литерал в строковое выражение. + * @ru @details Строковые литералы сами по себе не являются строковыми выражениями. * Обычно в операциях конкатенации это не вызывает проблем, так как второй операнд уже является строковым выражением, * и для него срабатывает сложение с литералом. Но есть ситуации, когда второй операнд тоже не является * строковым выражением. Например: @@ -483,6 +624,31 @@ struct expr_literal { * - Преобразовать другой операнд в строковое выражение: `result = "text" + e_num(intVar)`. * * Все эти способы работают и выдают одинаковый результат. Каким пользоваться - дело вкуса. + * + * @en @brief Converts a string literal to a string expression. + * @en @details String literals are not themselves string expressions. + * This usually does not cause problems in concatenation operations, since the second operand is already a string expression, + * and addition with a literal works for it. But there are situations when the second operand is not either + * string expression. For example: + * ```cpp + * int intVar = calculate(); + * ... + * res = "text" + intVar; + * ... + * res = intVar + "text"; + * ``` + * In this case, you can convert the literal to a string expression in two ways: + * - add _ss: `"text"_ss`, which converts the literal to simple_str_nt: `res = "text"_ss + intVar` + * - apply e_t: `e_t("text")`, which converts the literal to expr_literal: `res = e_t("text") + intVar` + * + * In the second method, the compiler can more aggressively apply optimizations related to what is known at compilation + * literal size. + * + * Although strictly speaking, in these situations you can use other methods: + * - Add an operand - an empty string expression: `result = eea + "text" + intVar`, `result = "text" + eea + intVar` + * - Convert another operand to a string expression: `result = "text" + e_num(intVar)`. + * + * All these methods work and give the same result. Which one to use is a matter of taste. */ template::Count> constexpr inline auto e_t(T&& s) { @@ -518,9 +684,11 @@ struct expr_literal_join { }; /*! - * @brief Оператор сложения для строкового выражения и строкового литерала такого же типа символов * @ingroup StrExprs - * @return Строковое выражение, объединяющее операнды + * @ru @brief Оператор сложения для строкового выражения и строкового литерала такого же типа символов. + * @ru @return Строковое выражение, объединяющее операнды. + * @en @brief The addition operator for a string expression and a string literal of the same character type. + * @en @return A string expression concatenating the operands. */ template::Count> constexpr inline auto operator+(const A& a, T&& s) { @@ -528,9 +696,11 @@ constexpr inline auto operator+(const A& a, T&& s) { } /*! - * @brief Оператор сложения для строкового литерала такого же типа символов и строкового выражения * @ingroup StrExprs - * @return Строковое выражение, объединяющее операнды + * @ru @brief Оператор сложения для строкового литерала такого же типа символов и строкового выражения. + * @ru @return Строковое выражение, объединяющее операнды. + * @en @brief The addition operator for a string literal of the same character type and string expression. + * @en @return A string expression concatenating the operands. */ template::Count> constexpr inline auto operator+(T&& s, const A& a) { @@ -538,12 +708,17 @@ constexpr inline auto operator+(T&& s, const A& a) { } /*! - * @brief Тип строкового выражения, возвращающего N заданных символов. * @ingroup StrExprs - * @details Количество символов и сам символ константы, т.е. задаются при компиляции. - * @tparam K - тип символа - * @tparam N - количество символов - * @tparam S - символ, по умолчанию пробел + * @ru @brief Тип строкового выражения, возвращающего N заданных символов. + * @ru @details Количество символов и сам символ константы, т.е. задаются при компиляции. + * @ru @tparam K - тип символа. + * @ru @tparam N - количество символов. + * @ru @tparam S - символ, по умолчанию пробел. + * @en @brief A type of string expression that returns N specified characters. + * @en @details The number of characters and the constant symbol itself, i.e. are specified during compilation. + * @en @tparam K is a symbol. + * @en @tparam N - number of characters. + * @en @tparam S - character, space by default. */ template struct expr_spaces { @@ -559,11 +734,14 @@ struct expr_spaces { }; /*! - * @brief Генерирует строку из N char пробелов * @ingroup StrExprs - * @tparam N - Количество пробелов - * @return строковое выражение для N char пробелов - * @details Пример: + * @ru @brief Генерирует строку из N char пробелов. + * @ru @tparam N - Количество пробелов. + * @ru @return строковое выражение для N char пробелов. + * @en @brief Generates a string of N char spaces. + * @en @tparam N - Number of spaces. + * @en @return string expression for N char spaces. + * @details @ru Пример: @en Example: @~ * ```cpp * stringa text = e_spca<10>() + text + e_spca<10>(); * ``` @@ -574,11 +752,14 @@ constexpr inline auto e_spca() { } /*! - * @brief Генерирует строку из N wchar_t пробелов * @ingroup StrExprs - * @tparam N - Количество пробелов - * @return строковое выражение для N wchar_t пробелов - * @details Пример: + * @ru @brief Генерирует строку из N wchar_t пробелов. + * @ru @tparam N - Количество пробелов. + * @ru @return строковое выражение для N wchar_t пробелов. + * @en @brief Generates a string of N wchar_t spaces. + * @en @tparam N - Number of spaces. + * @en @return string expression for N wchar_t spaces. + * @details @ru Пример: @en Example: @~ * ```cpp * stringw text = e_spcw<10>() + text + e_spcw<10>(); * ``` @@ -589,11 +770,15 @@ constexpr inline auto e_spcw() { } /*! - * @brief Тип строкового выражения, возвращающего N заданных символов. * @ingroup StrExprs - * @tparam K - тип символа - * @details Количество символов и сам символ переменные, т.е. могут меняться в рантайм. - * Напрямую обычно не используется, создается через e_c() + * @ru @brief Тип строкового выражения, возвращающего N заданных символов. + * @ru @tparam K - тип символа. + * @ru @details Количество символов и сам символ переменные, т.е. могут меняться в рантайм. + * Напрямую обычно не используется, создается через e_c(). + * @en @brief A type of string expression that returns N specified characters. + * @en @tparam K is a symbol. + * @en @details The number of characters and the character itself are variable, i.e. can change at runtime. + * Usually not used directly, created via e_c(). */ template struct expr_pad { @@ -611,12 +796,17 @@ struct expr_pad { }; /*! - * @brief Генерирует строку из l символов s типа K * @ingroup StrExprs - * @tparam K - тип символа - * @param l - количество символов - * @param s - символ - * @return строковое выражение, генерирующее строку из l символов k + * @ru @brief Генерирует строку из l символов s типа K. + * @ru @tparam K - тип символа. + * @ru @param l - количество символов. + * @ru @param s - символ. + * @ru @return строковое выражение, генерирующее строку из l символов k. + * @en @brief Generates a string of l characters s of type K. + * @en @tparam K is a symbol. + * @en @param l - number of characters. + * @en @param s - symbol. + * @en @return a string expression that generates a string of l characters k. */ template constexpr inline auto e_c(size_t l, K s) { @@ -624,12 +814,17 @@ constexpr inline auto e_c(size_t l, K s) { } /*! - * @brief Строковое выражение условного выбора * @ingroup StrExprs - * @tparam A Тип ветки для true - * @tparam B Тип ветки для false - * @details Выражение, в зависимости от истинности условия генерирующее либо выражение A, либо выражение B. - * Напрямую тип обычно не используется, создаётся через e_choice() + * @ru @brief Строковое выражение условного выбора. + * @ru @tparam A Тип ветки для true. + * @ru @tparam B Тип ветки для false. + * @ru @details Выражение, в зависимости от истинности условия генерирующее либо выражение A, либо выражение B. + * Напрямую тип обычно не используется, создаётся через e_choice(). + * @en @brief Conditional selection string expression. + * @en @tparam A Branch type for true. + * @en @tparam B Branch type for false. + * @en @details An expression that, depending on the truth of the condition, generates either expression A or expression B. + * The type is usually not used directly; it is created via e_choice(). */ template B> struct expr_choice { @@ -648,11 +843,15 @@ struct expr_choice { }; /*! - * @brief Строковое выражение условного выбора * @ingroup StrExprs - * @tparam A Тип ветки для true - * @details Выражение, в зависимости от истинности условия генерирующее либо выражение A, либо пустую строку. - * Напрямую тип обычно не используется, создаётся через e_if() + * @ru @brief Строковое выражение условного выбора. + * @ru @tparam A Тип ветки для true. + * @ru @details Выражение, в зависимости от истинности условия генерирующее либо выражение A, либо пустую строку. + * Напрямую тип обычно не используется, создаётся через e_if(). + * @en @brief Conditional selection string expression. + * @en @tparam A Branch type for true. + * @en @details An expression that, depending on the truth of the condition, generates either expression A or an empty string. + * Title type usually not used, create through e_if(). */ template struct expr_if { @@ -670,11 +869,11 @@ struct expr_if { }; /*! - * @brief Строковое выражение условного выбора * @ingroup StrExprs - * @tparam A Тип ветки для true - * @details Выражение, в зависимости от истинности условия генерирующее либо выражение A, либо строку из строкового литерала. - * Напрямую тип обычно не используется, создаётся через e_choice() + * @ru @brief Строковое выражение условного выбора. + * @ru @tparam A Тип ветки для true. + * @ru @details Выражение, в зависимости от истинности условия генерирующее либо выражение A, либо строку из строкового литерала. + * Напрямую тип обычно не используется, создаётся через e_choice(). * * Так как строковые литералы не являются строковыми выражениями, то использовать их в виде одиночного выражения в частях * e_choice или e_if требовало бы их обрамления какими-либо конструкциями, преобразующими их в строковое выражение. @@ -693,6 +892,27 @@ struct expr_if { * e_choice(condition, "false", "true"); * e_if(!condition, "empty"); * ``` + * @en @brief Conditional selection string expression. + * @en @tparam A Branch type for true. + * @en @details An expression that, depending on the truth of the condition, generates either expression A or a string from a string literal. + * The type is usually not used directly; it is created via e_choice(). + * + * Since string literals are not string expressions, use them as a single expression in parts + * e_choice or e_if would require them to be surrounded by some constructs that convert them to a string expression. + * You would have to write something like this: + * ```cpp + * e_choice(condition, text, e_t("empty")); + * e_choice(condition, text, eea + "empty"); + * e_choice(condition, text, "empty"_ss); + * e_if(!condition, "empty"_ss); + * ``` + * This, on the one hand, clutters up the code, on the other, makes it less optimal. + * These overloads use expr_choice_one_lit and expr_choice_two_lit, allowing you to write like this: + * ```cpp + * e_choice(condition, text, "empty"); + * e_choice(condition, "false", "true"); + * e_if(!condition, "empty"); + * ``` */ template struct expr_choice_one_lit { @@ -716,10 +936,10 @@ struct expr_choice_one_lit { }; /*! - * @brief Строковое выражение условного выбора * @ingroup StrExprs - * @details Выражение, в зависимости от истинности условия генерирующее либо один строковый литерал, либо другой. - * Напрямую тип обычно не используется, создаётся через e_choice() + * @ru @brief Строковое выражение условного выбора. + * @ru @details Выражение, в зависимости от истинности условия генерирующее либо один строковый литерал, либо другой. + * Напрямую тип обычно не используется, создаётся через e_choice(). * * Так как строковые литералы не являются строковыми выражениями, то использовать их в виде одиночного выражения в частях * e_choice или e_if требовало бы их обрамления какими-либо конструкциями, преобразующими их в строковое выражение. @@ -738,6 +958,26 @@ struct expr_choice_one_lit { * e_choice(condition, "false", "true"); * e_if(!condition, "empty"); * ``` + * @en @brief Conditional selection string expression. + * @en @details An expression that, depending on the truth of the condition, generates either one string literal or another. + * The type is usually not used directly; it is created via e_choice(). + * + * Since string literals are not string expressions, use them as a single expression in parts + * e_choice or e_if would require them to be surrounded by some constructs that convert them to a string expression. + * You would have to write something like this: + * ```cpp + * e_choice(condition, text, e_t("empty")); + * e_choice(condition, text, eea + "empty"); + * e_choice(condition, text, "empty"_ss); + * e_if(!condition, "empty"_ss); + * ``` + * This, on the one hand, clutters up the code, on the other, makes it less optimal. + * These overloads use expr_choice_one_lit and expr_choice_two_lit, allowing you to write like this: + * ```cpp + * e_choice(condition, text, "empty"); + * e_choice(condition, "false", "true"); + * e_if(!condition, "empty"); + * ``` */ template struct expr_choice_two_lit { @@ -764,24 +1004,33 @@ struct expr_choice_two_lit { }; /*! - * @brief Создание условного строкового выражения expr_choice * @ingroup StrExprs - * @tparam A - Тип выражение при истинности условия, выводится из аргумента - * @tparam B - Тип выражения при ложности условия, выводится из аргумента - * @param c - булево условие - * @param a - строковое выражение, выполняющееся при `c == true` - * @param b - строковое выражение, выполняющееся при `c == false` - * @details Служит для возможности в одном выражении выбирать разные варианты в зависимости от условия. + * @ru @brief Создание условного строкового выражения expr_choice. + * @ru @tparam A - Тип выражение при истинности условия, выводится из аргумента. + * @ru @tparam B - Тип выражения при ложности условия, выводится из аргумента. + * @ru @param c - булево условие. + * @ru @param a - строковое выражение, выполняющееся при `c == true`. + * @ru @param b - строковое выражение, выполняющееся при `c == false`. + * @ru @details Служит для возможности в одном выражении выбирать разные варианты в зависимости от условия. + * @en @brief Create a conditional string expression expr_choice. + * @en @tparam A - Type expression when the condition is true, inferred from the argument. + * @en @tparam B - The type of expression when the condition is false, inferred from the argument. + * @en @param c is a Boolean condition. + * @en @param a is a string expression that is executed when `c == true`. + * @en @param b is a string expression that is executed when `c == false`. + * @en @details Serves to allow you to select different options in one expression depending on the condition. * - * Примеры: + * @ru Примеры: @en Example: @~ * ```cpp * columns_metadata.emplace_back(e_choice(name.is_empty(), "?column?", name) + "::" + metadata_column.type.to_string()); * ``` * ```cpp * lstringa<512> str = e_choice(!ret_type_resolver_, sql_value::type_name(ret_type_), "any") + " " + name_ + "("; * ``` - * Иначе такие операции приходилось бы разбивать на несколько модификаций строки или применению временных строк, + * @ru Иначе такие операции приходилось бы разбивать на несколько модификаций строки или применению временных строк, * что не оптимально и снизит производительность. (Это проверяется в бенчмарке "Build Full Func Name") + * @en Otherwise, such operations would have to be split into several string modifications or the use of temporary strings, + * which is not optimal and will reduce performance. (This is checked in the "Build Full Func Name" benchmark) */ template B> inline constexpr auto e_choice(bool c, const A& a, const B& b) { @@ -789,8 +1038,9 @@ inline constexpr auto e_choice(bool c, const A& a, const B& b) { } /*! - * @brief Перегрузка e_choice, когда третий аргумент - строковый литерал * @ingroup StrExprs + * @ru @brief Перегрузка e_choice, когда третий аргумент - строковый литерал. + * @en @brief Overload e_choice when the third argument is a string literal. */ template::Count> inline constexpr auto e_choice(bool c, const A& a, T&& str) { @@ -798,16 +1048,18 @@ inline constexpr auto e_choice(bool c, const A& a, T&& str) { } /*! - * @brief Перегрузка e_choice, когда второй аргумент - строковый литерал * @ingroup StrExprs + * @ru @brief Перегрузка e_choice, когда второй аргумент - строковый литерал. + * @en @brief Overload e_choice when the second argument is a string literal. */ template::Count> inline constexpr auto e_choice(bool c, T&& str, const A& a) { return expr_choice_one_lit{str, a, c}; } /*! - * @brief Перегрузка e_choice, когда второй и третий аргумент - строковые литералы * @ingroup StrExprs + * @ru @brief Перегрузка e_choice, когда второй и третий аргумент - строковые литералы. + * @en @brief Overload e_choice when the second and third arguments are string literals. */ template::Count, size_t M = const_lit_for::symb_type, L>::Count> inline constexpr auto e_choice(bool c, T&& str_a, L&& str_b) { @@ -815,43 +1067,56 @@ inline constexpr auto e_choice(bool c, T&& str_a, L&& str_b) { } /*! - * @brief Создание условного строкового выражения expr_if * @ingroup StrExprs - * @tparam A - Тип выражение при истинности условия, выводится из аргумента - * @param c - булево условие - * @param a - строковое выражение, выполняющееся при `c == true` - * @details Служит для возможности в одном выражении генерировать в зависимости от условия либо указанный вариант, либо пустую строку. - * - * Примеры: + * @ru @brief Создание условного строкового выражения expr_if + * @ru @tparam A - Тип выражение при истинности условия, выводится из аргумента + * @ru @param c - булево условие + * @ru @param a - строковое выражение, выполняющееся при `c == true` + * @ru @details Служит для возможности в одном выражении генерировать в зависимости от условия либо указанный вариант, либо пустую строку. + * @en @brief Creating a conditional string expression expr_if + * @en @ingroup StrExprs + * @en @tparam A - Type expression when the condition is true, inferred from the argument + * @en @param c - boolean condition + * @en @param a - string expression executed when `c == true` + * @en @details Serves to allow one expression to generate, depending on the condition, either the specified option or an empty string. + * + * @ru Примеры: @en Example @~ * ```cpp * void sql_func_info::build_full_name() { * // Временный буфер для результата, возьмём с запасом + * // Temporary buffer for the result, take it with reserve * lstringa<512> str = e_choice(!ret_type_resolver_, sql_value::type_name(ret_type_), "any") + " " + name_ + "("; * * bool add_comma = false; * * for (const auto& param : params_) { * str += e_if(add_comma, ", ") + e_if(param.optional_, "["); - * param.allowed_types.to_string(str); // Добавляет к str названия допустимых типов + * // Добавляет к str названия допустимых типов + * // Adds the names of valid types to str + * param.allowed_types.to_string(str); * if (param.optional_) { * str += "]"; * } * add_comma = true; * } * // Сохраним в stringa + * // Save it in stringa * full_name_ = str + e_if(unlim_params_, e_if(add_comma, ", ") + "...") + ")"; * } * ``` - * Иначе такие операции приходилось бы разбивать на несколько модификаций строки или применению временных строк, + * @ru Иначе такие операции приходилось бы разбивать на несколько модификаций строки или применению временных строк, * что не оптимально и снизит производительность. (Этот пример проверяется в бенчмарке "Build Full Func Name") + * @en Otherwise, such operations would have to be split into several string modifications or the use of temporary strings, + * which is not optimal and will reduce performance. (This example is tested in the "Build Full Func Name" benchmark) */ template inline constexpr auto e_if(bool c, const A& a) { return expr_if{a, c}; } /*! - * @brief Перегрузка e_if, когда второй аргумент - строковый литерал * @ingroup StrExprs + * @ru @brief Перегрузка e_if, когда второй аргумент - строковый литерал. + * @en @brief Overload e_if when the second argument is a string literal. */ template::Count> inline constexpr auto e_if(bool c, T&& str) { @@ -860,10 +1125,13 @@ inline constexpr auto e_if(bool c, T&& str) { } /*! - * @brief Тип для использования std::string и std::string_view как источников в строковых выражениях * @ingroup StrExprs - * @tparam K - тип символа - * @tparam T - тип источника + * @ru @brief Тип для использования std::string и std::string_view как источников в строковых выражениях. + * @ru @tparam K - тип символа. + * @ru @tparam T - тип источника. + * @en @brief A type for using std::string and std::string_view as sources in string expressions. + * @en @tparam K is a symbol. + * @en @tparam T - source type. */ template struct expr_stdstr { @@ -883,8 +1151,9 @@ struct expr_stdstr { }; /*! - * @brief Оператор сложения для char строкового выражения и std::string * @ingroup StrExprs + * @ru @brief Оператор сложения для char строкового выражения и std::string. + * @en @brief Addition operator for char string expression and std::string. */ template A> auto operator+(const A& a, const std::string& s) { @@ -892,8 +1161,9 @@ auto operator+(const A& a, const std::string& s) { } /*! - * @brief Оператор сложения для std::string и char строкового выражения * @ingroup StrExprs + * @ru @brief Оператор сложения для std::string и char строкового выражения. + * @en @brief Addition operator for std::string and char string expression. */ template A> auto operator+(const std::string& s, const A& a) { @@ -901,8 +1171,9 @@ auto operator+(const std::string& s, const A& a) { } /*! - * @brief Оператор сложения для char строкового выражения и std::string_view * @ingroup StrExprs + * @ru @brief Оператор сложения для char строкового выражения и std::string_view. + * @en @brief Addition operator for char string expression and std::string_view. */ template A> auto operator+(const A& a, const std::string_view& s) { @@ -910,8 +1181,9 @@ auto operator+(const A& a, const std::string_view& s) { } /*! - * @brief Оператор сложения для std::string_view и char строкового выражения * @ingroup StrExprs + * @ru @brief Оператор сложения для std::string_view и char строкового выражения. + * @en @brief Addition operator for std::string_view and char string expression. */ template A> auto operator+(const std::string_view& s, const A& a) { @@ -919,8 +1191,9 @@ auto operator+(const std::string_view& s, const A& a) { } /*! - * @brief Оператор сложения для wchar_t строкового выражения и std::wstring * @ingroup StrExprs + * @ru @brief Оператор сложения для wchar_t строкового выражения и std::wstring. + * @en @brief Addition operator for wchar_t string expression and std::wstring. */ template A> auto operator+(const A& a, const std::wstring& s) { @@ -928,8 +1201,9 @@ auto operator+(const A& a, const std::wstring& s) { } /*! - * @brief Оператор сложения для std::wstring и wchar_t строкового выражения * @ingroup StrExprs + * @ru @brief Оператор сложения для std::wstring и wchar_t строкового выражения. + * @en @brief Addition operator for std::wstring and wchar_t string expression. */ template A> auto operator+(const std::wstring& s, const A& a) { @@ -937,8 +1211,9 @@ auto operator+(const std::wstring& s, const A& a) { } /*! - * @brief Оператор сложения для wchar_t строкового выражения и std::wstring_view * @ingroup StrExprs + * @ru @brief Оператор сложения для wchar_t строкового выражения и std::wstring_view. + * @en @brief Addition operator for wchar_t string expression and std::wstring_view. */ template A> auto operator+(const A& a, const std::wstring_view& s) { @@ -946,8 +1221,9 @@ auto operator+(const A& a, const std::wstring_view& s) { } /*! - * @brief Оператор сложения для std::wstring_view и wchar_t строкового выражения * @ingroup StrExprs + * @ru @brief Оператор сложения для std::wstring_view и wchar_t строкового выражения. + * @en @brief Addition operator for std::wstring_view and wchar_t string expression. */ template A> auto operator+(const std::wstring_view& s, const A& a) { @@ -955,9 +1231,11 @@ auto operator+(const std::wstring_view& s, const A& a) { } /*! - * @brief Оператор сложения для совместимого с wchar_t строкового выражения (char16_t или - * char32_t, в зависимости от компилятора) и std::wstring * @ingroup StrExprs + * @ru @brief Оператор сложения для совместимого с wchar_t строкового выражения (char16_t или + * char32_t, в зависимости от компилятора) и std::wstring. + * @en @brief Addition operator for wchar_t compatible string expression (char16_t or + * char32_t, depending on the compiler) and std::wstring. */ template A> auto operator+(const A& a, const std::wstring& s) { @@ -965,9 +1243,11 @@ auto operator+(const A& a, const std::wstring& s) { } /*! - * @brief Оператор сложения для std::wstring и совместимого с wchar_t строкового выражения - * (char16_t или char32_t, в зависимости от компилятора) * @ingroup StrExprs + * @ru @brief Оператор сложения для std::wstring и совместимого с wchar_t строкового выражения + * (char16_t или char32_t, в зависимости от компилятора). + * @en @brief Addition operator for std::wstring and wchar_t-compatible string expression + * (char16_t or char32_t, depending on the compiler). */ template A> auto operator+(const std::wstring& s, const A& a) { @@ -975,9 +1255,11 @@ auto operator+(const std::wstring& s, const A& a) { } /*! - * @brief Оператор сложения для совместимого с wchar_t строкового выражения (char16_t или - * char32_t, в зависимости от компилятора) и std::wstring_view * @ingroup StrExprs + * @ru @brief Оператор сложения для совместимого с wchar_t строкового выражения (char16_t или + * char32_t, в зависимости от компилятора) и std::wstring_view. + * @en @brief Addition operator for wchar_t compatible string expression (char16_t or + * char32_t, depending on the compiler) and std::wstring_view. */ template A> auto operator+(const A& a, const std::wstring_view& s) { @@ -985,9 +1267,11 @@ auto operator+(const A& a, const std::wstring_view& s) { } /*! - * @brief Оператор сложения для std::wstring_view и совместимого с wchar_t строкового выражения - * (char16_t или char32_t, в зависимости от компилятора) * @ingroup StrExprs + * @ru @brief Оператор сложения для std::wstring_view и совместимого с wchar_t строкового выражения + * (char16_t или char32_t, в зависимости от компилятора). + * @en @brief Addition operator for std::wstring_view and wchar_t-compatible string expression + * (char16_t or char32_t, depending on the compiler). */ template A> auto operator+(const std::wstring_view& s, const A& a) {