如何解决参数包参数类型
我修改了 https://en.cppreference.com/w/cpp/language/parameter_pack 中的示例以将字符串保存在变量中。我的代码
#include <string>
void tprintf(std::string& str,const std::string& format)
{
str += format;
}
template <typename T,typename... Targs>
void tprintf(std::string& str,const std::string& format,T arg,Targs ...Fargs)
{
for ( int i = 0; i < format.size(); i++ )
{
if ( format.at(i) == '%' )
{
if (format.at(i + 1) == 'd')
{
std::cout << "== 'd' -variable = " << arg << std::endl;
str += std::to_string(arg);
}
else if (format.at(i + 1) == 's')
{
std::cout << "== 's'" << std::endl;
str += arg;
}
tprintf(str,(i + 2 < format.size() ? format.substr(i + 2) : ""),Fargs...);
break;
}
str += format.at(i);
}
}
int main()
{
std::string str;
int age = 24;
std::string name("Hugo");
tprintf(str,"Name: %s,age: %d years\n",name,age);
std::cout << "result = " << str << std::endl;
}
error: no matching function for call to ‘to_string(std::__cxx11::basic_string<char>&)’
str += std::to_string(arg);
我认为参数包扩展为
-
tprintf(std::string&,const std::string&,std::string,int)
arg 是std::string
-
tprintf(std::string&,int)
arg 是int
,我可以调用std::to_string(arg)
但似乎arg
有另一种类型而不是int
(std::string
或其他东西)? 当我删除std::to_string
调用时,我得到了一些神秘字符。
如何将年龄值转换为 string
并将其附加到 str
?
解决方法
tprintf(std::string&,const std::string&,std::string,int)
因此,这里是正确的:
str += std::to_string(arg);
arg
是一个 std::string
,并且没有这样的 std::to_string
重载。
无论 T
是什么类型,生成的模板都必须是有效的 C++ 代码。即使对应的格式化字符是 d
,函数中的所有内容也必须是有效的 C++ 代码。
一般来说,尝试在类型安全的 C++ 中实现 C 风格的 printf
格式没有多大意义。您已经知道需要格式化的内容,因为您知道相应参数的类型。
您在 C 样式的 printf
字符串(例如 %s
或 %d
)中使用不同格式说明符的唯一原因是因为该 C 函数不知道会得到什么作为参数传递给它,因此它依赖于实际的格式说明符来知道它是什么。
这显然不是 C++ 的情况。您的格式说明符本身可以只是一个 %
,没有别的。您确切地知道传入的是什么参数。因此,仅定义三个重载函数要简单得多:
template <typename... Targs>
void tprintf(std::string& str,const std::string& format,int arg,Targs ...args)
{
// Just the code that formats an int
}
template <typename... Targs>
void tprintf(std::string& str,const std::string &arg,Targs ...args)
{
// Just the code that formats a std::string
}
void tprintf(std::string& str,const std::string& format)
{
// Nothing more to format,just adds everything else in "format" to "str".
}
在前两种情况下,所有需要发生的事情就是自己搜索第一个 format
占位符的 %
,将它之前的所有内容复制到 str
中,然后通过格式化参数,然后递归地重新调用 tprintf
与剩余的 args
,以及 format
中剩余的内容。
附言使用转发引用,“Targs && ...args”与 std::forward
一起将成为后续调整。
if 语句的所有分支都被编译。编译器试图将字符串参数传递给字符串,并且不存在重载。
它不会在运行时发生的事实是无关紧要的。在编译时,编译器需要知道什么
tprintf(str,"Name: %s,age: %d years\n",name,age);
做和做什么
tprintf(str,"Name: %d,age);
愿意。
考虑不要两次包含类型信息。你已经知道 name 是一个字符串,age 是一个整数,在格式字符串中重复它是没有意义的。
我建议在格式字符串中使用位置命令,因为这也使本地化更加实用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。