[英]parameter packs parameter type
I have modified the sample from https://en.cppreference.com/w/cpp/language/parameter_pack to save the string in a variable.我已经修改了https://en.cppreference.com/w/cpp/language/parameter_pack中的示例,以将字符串保存在变量中。 My code
我的代码
#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;
}
When compile the code I get the following error:编译代码时出现以下错误:
error: no matching function for call to ‘to_string(std::__cxx11::basic_string<char>&)’
str += std::to_string(arg);
I thought the parameter pack expands to我认为参数包扩展到
tprintf(std::string&, const std::string&, std::string, int)
<- arg
is std::string
tprintf(std::string&, const std::string&, std::string, int)
<- arg
是std::string
tprintf(std::string&, const std::string&, int)
<- arg
is int
and I can call std::to_string(arg)
But it seems that arg
has another type than int
( std::string
or something else)? tprintf(std::string&, const std::string&, int)
<- arg
是int
,我可以调用std::to_string(arg)
但似乎arg
具有除int
之外的另一种类型( std::string
或其他类型) ? When I remove the std::to_string
call I get some cryptic characters.std::to_string
调用时,我得到了一些神秘字符。 How can I convert the value for the age to a string
and append it to str
?如何将年龄的值转换为
string
并将 append 转换为str
?
tprintf(std::string&, const std::string&, std::string, int) <- arg is std::string
tprintf(std::string&, const std::string&, std::string, int) <- arg 是 std::string
Correct, therefore, here:因此,这里是正确的:
str += std::to_string(arg);
arg
is a std::string
, and there is no such std::to_string
overload. arg
是一个std::string
,并且没有这样的std::to_string
重载。
No matter what type T
is, the resulting template must be valid C++ code.无论
T
是什么类型,生成的模板必须是有效的 C++ 代码。 Even if the corresponding formatting character is d
, everything in the function must still be valid C++ code.即使对应的格式化字符是
d
, function 中的所有内容仍然必须是有效的 C++ 代码。
In general, attempting to implement C-style printf
formatting, in type-safe C++ doesn't make much sense.一般来说,尝试在类型安全的 C++ 中实现 C 风格的
printf
格式没有多大意义。 You already know what needs to be formatted simply by the virtue of the fact that you know the type of the corresponding parameter.由于您知道相应参数的类型,因此您已经知道需要格式化什么。
The only reason you have different formatting specifiers in C-style printf
strings, such as %s
or %d
, is because this C function has no clue, whatsoever, what is getting to passed to it, as a parameter, so it relies on the actual formatting specifier to know what it is.您在 C 风格
printf
字符串(例如%s
或%d
)中有不同格式说明符的唯一原因是因为这个 C function 没有任何线索,所以它没有任何线索实际的格式说明符以了解它是什么。
This obviously isn't the case with C++. C++ 显然不是这种情况。 Your formatting specifier can be just a
%
, by itself, with nothing else.您的格式说明符本身可以只是一个
%
,没有别的。 You know exactly what parameter gets passed in. Therefore, it's much simpler to merely define three overloaded functions:您确切地知道传入了什么参数。因此,仅定义三个重载函数要简单得多:
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& format, 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".
}
In the first two cases, all that needs to happen is to search format
for the first %
place-holder by itself, copy everything before prior to it into str
, followed by the formatted parameter, and then recursively re-invoke tprintf
with the remaining args
, and what's left in the format
.在前两种情况下,只需要自行搜索第一个
%
占位符的format
,将其之前的所有内容复制到str
中,然后是格式化参数,然后递归地重新调用tprintf
其余的args
,以及format
中剩下的内容。
PS Using forwarding references, "Targs &&...args", together with std::forward
, will be a follow-up tweak. PS 使用转发引用,“Targs &&...args”,连同
std::forward
,将是一个后续调整。
All branches of an if statement are compiled. if 语句的所有分支都被编译。 The compiler is attempting to pass the string argument to to string, and no overload exists.
编译器正在尝试将字符串参数传递给字符串,并且不存在重载。
The fact that it doesn't happen at runtime is irrelevant.它不会在运行时发生的事实是无关紧要的。 At compile time, the compiler needs to know what
在编译时,编译器需要知道什么
tprintf(str, "Name: %s, age: %d years\n", name, age);
does and what做什么和做什么
tprintf(str, "Name: %d, age: %d years\n", name, age);
would do.会做。
Consider not including type information twice.考虑不包括类型信息两次。 You already know that name is a string and age is an integer, repeating it in the format string is pointless.
您已经知道 name 是一个字符串,而 age 是一个 integer,在格式字符串中重复它是没有意义的。
I'd advise positional commands in a format string, as that makes localization far more practical as well.我建议使用格式字符串的位置命令,因为这也使本地化更加实用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.