Нужна помощь, чтобы понять, как std :: format может проверить свою строку формата при скомпилированном времениC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Нужна помощь, чтобы понять, как std :: format может проверить свою строку формата при скомпилированном времени

Сообщение Anonymous »

Из любопытства и с надеждой на изучение полезных методов компиляции, я пытаюсь понять, как std :: format выполняет проверку времени компиляции его аргументов. {} Заполнители в строке формата, предоставленная во время компиляции, меньше или равна количеству предоставленных аргументов. Вот моя попытка: < /p>

Код: Выделить всё

#include 

// compile-time count of "{}" inside "str"
consteval int count_occurrences(std::string_view str) {
int count = 0;
size_t pos = 0;
std::string_view pattern("{}");

while ((pos = str.find(pattern, pos)) != std::string_view::npos) {
++count;
pos += pattern.length();
}

return count;
}

template 
struct FormatStringImpl {
template 
consteval FormatStringImpl(Str const& str) : frmt(str) {
// frmt is not considered as a constant expression so the next line
// obviously doesn't compile
auto constexpr n = count_occurrences(frmt);
static_assert(sizeof...(Args) >= n, "wrong number of arguments");
}
std::string_view frmt;
};

// don't try to deduce Args from FormatString in foo call
template 
using FormatString = FormatStringImpl;

template 
consteval void foo([[maybe_unused]] FormatString const frmt,
[[maybe_unused]] Args&&... args) {};
demo
Общая идея состоит в том, чтобы выполнить проверку во время строительства времени компиляции аргумента frmt (и не внутри foo () , где не может использоваться вход их значения). < /p>
Теперь я застрял, потому что я не вижу, как продолжить проверку внутри конструктора. Моя попытка, очевидно, терпит неудачу, потому что я пытаюсь инициализировать выражение времени компиляции из формально неизменного выражения. Глядя на стандартную реализацию библиотеки быстро теряет меня в деталях, которые мешают мне получить основные идеи (которые я мог бы повторно использовать с помощью более подробных проверок). < /P>
Я нашел возможное решение из этого другого ответа: < /p>
consteval FormatStringImpl(Str const& str) : frmt(str) {
// frmt is not considered as a constant expression so I'm not using a constexpr variable anymore
auto n = count_occurrences(frmt);
if (sizeof...(Args) < static_cast(n))
{
// is it legal?!
throw "wrong number of arguments";
};

demo
Здесь я удаляю необходимость постоянного выражения, но я думал, что использование thress внутри contexpr /

Код: Выделить всё

consteval
Функция была плохо сформирована, и я не уверен, что для компилятора необходимо издать ошибку, если он столкнулся с Throw во время оценки времени компиляции (AFAIK, это IFNDR: https://timsong-cpp.github.io/cppw/n486 ... onstexpr#6. двигаться дальше с чеком? Есть ли способ использовать постоянное выражение (и, возможно, static_assert )? Можно ли использовать решение Thress ( update afaik, внедрение MSVC использует Throw ).

Подробнее здесь: https://stackoverflow.com/questions/796 ... -compile-t
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»