如何在C ++ 20/23中的SprintF函数验证格式指定符的数量是否与编译时间时提供的参数的数量匹配?

问题描述 投票:0回答:1
#include <iostream> template <int N> constexpr size_t count_percents(const char (&s)[N]) { size_t count = 0; for (size_t i = 0; i < N; i++) if (s[i] == '%') ++count; return count; } template <int N, typename... Args> constexpr std::string Sprintf(const char (&format)[N], Args&&... args) { if (count_percents(format) != sizeof...(args)) throw std::invalid_argument("wrong number of placeholders in format string"); return (std::to_string(args) + ...); } int main() { std::cout << Sprintf("%%", 1, 2); // outputs "12", ok // ideally wouldn't compile (but does - then throws runtime exception) std::cout << Sprintf("%", 1, 2); }

I发现了这个答案

有帮助,但是它并没有解决我的用例,在该情况下,我希望根据传递给非consteval函数的参数数量编译时间错误。 (如果我想进行的所有编译时间检查仅取决于格式字符串本身的内容。)

there是您的示例的修改版本,该版本应有效: #include <iostream> #include <type_traits> constexpr size_t count_percents(const char* s) { size_t count = 0; while (*s != '\0') { if (*(s++) == '%') { count++; } } return count; } template <typename... Args> struct format_args { const char* format; consteval format_args(const char* format) : format(format) { if (count_percents(format) != sizeof...(Args)) { throw std::invalid_argument("wrong number of placeholders in format string"); } } }; template <typename... Args> constexpr std::string Sprintf(format_args<std::type_identity_t<Args>...> format, Args&&... args) { return (std::to_string(args) + ...); } int main() { std::cout << Sprintf("%%", 1, 2); // outputs "12", ok // ideally wouldn't compile (but does - then throws runtime exception) std::cout << Sprintf("%", 1, 2); }

您引用的答案是一个很好的起点。但是,它不会解决将包装

Args传递给format_args

的构造函数。
c++ c++20 constexpr c++23 consteval
1个回答
0
投票
std::type_identity_t

。如果您像:

那样天真地声明它:
constexpr std::string Sprintf(format_args<Args...> format, Args&&... args) { 
  // impl 
}

...它不起作用,因为当编译器进行模板分辨率时,它会从左到右检查参数并尝试匹配它们。它将首先尝试从您传递的第一个参数的类型中推断出来。嗯,不能因为它是一个。因此,它尖叫了一个错误!

这里是here conthen派上用场的地方:它使
Args...
pack内部的the the the the nim in the non deded ContextInd contectiondecontectiondectessine contectiond contectiond contectisty
什么应该是稍后的(从

const char*

的类型中可以)。

	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.