Код: Выделить всё
#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) {};
Общая идея состоит в том, чтобы выполнить проверку во время строительства времени компиляции аргумента 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Подробнее здесь: https://stackoverflow.com/questions/796 ... -compile-t
Мобильная версия