[英]pass multiple arguments to another function using template variadic function
Let us consider the following function: 让我们考虑以下功能:
static void Print(const Type& type, const std::string& message, const std::string& variable) {
Log(type, message + ": " + variable);
}
I'd like it to pass arbitrary number of variables (I mean std::string &
variable - this holds a variable name) and then send them via Log()
function together and for this reason, I've considered using template variadic function (an overloaded Print()
). 我希望它传递任意数量的变量(我的意思是
std::string &
variable - 它保存一个变量名),然后通过Log()
函数一起发送它们,因此我考虑使用模板可变参数函数(重载的Print()
)。 I'd define it like this: 我这样定义它:
template <typename Arg, typename ...Args)
static void Print(const Type& type, const std::string& message,
const Arg& arg, const Args&... args);
and then: 接着:
Print(type, message, args...);
Log(type, message + ": " + arg);
Just an idea, this would work most likely like this: 只是一个想法,这很可能会像这样:
args...
would be passed and Print()
function would be called recursively until there's no arguments left, args...
将被传递, Print()
函数将被递归调用,直到没有参数为止, Log()
function would be called which would basically log it every time. Log()
函数,它基本上每次都会记录它。 What I would need to do is to somehow remember arg
value but it would require calling Print()
with an additional argument and I don't really like this idea. 我需要做的是以某种方式记住
arg
值,但它需要使用另一个参数调用Print()
,我真的不喜欢这个想法。 Do you have any other clues? 你还有其他线索吗?
Depending on the desired format, you might be able to get away with a fold expression: 根据所需的格式,您可以使用折叠表达式:
template<class... Args>
void Print(const Type& type, const std::string& message, const Args&... arg)
{
std::stringstream strstr;
strstr << message << ": "; // Or your prefix computation, whatever you want.
((strstr << arg << ", "), ...);
std::string toLog = strstr.str();
// Remove last separator characters.
toLog.erase(toLog.end() - 2, toLog.end());
Log(type, strstr.str());
}
It seems to me that the Max Langhof's solution is simple and elegant. 在我看来,Max Langhof的解决方案简单而优雅。
Unfortunately it uses template folding that is available only starting from C++17. 不幸的是,它使用的模板折叠仅从C ++ 17开始提供。
I propose a C++11/C++14 version that, instead template folding, uses the old trick of the initialization of an unused array 我提出了一个C ++ 11 / C ++ 14版本,而不是模板折叠,它使用了未使用数组初始化的旧技巧
template <typename ... Args>
void Print (Type const & type, std::string const & message,
Args const & ... arg)
{
using unused = int[];
std::stringstream strstr;
strstr << message << ": ";
(void)unused { 0, (strstr << arg << ", ", 0)... };
std::string toLog = strstr.str();
// Remove last separator characters.
toLog.erase(toLog.end() - 2, toLog.end());
Log(type, strstr.str());
}
I simplified your example a bit, so assuming I correctly understood what you want to do, you can do one of the 2 following solutions, if the C++17 folds suggested by @Max Langhof are not supported by your compiler. 我简化了你的例子,所以假设我正确地理解你想做什么,你可以做以下两个解决方案之一,如果你的编译器不支持@Max Langhof建议的C ++ 17折叠。
Both of them work on any type that supports operator+ for doing the correct thing, but are simple to modify if your concat function is something else. 它们都可以在任何支持operator +的类型上运行,但是如果你的concat函数是其他东西,它们很容易修改。
template <typename Arg>
static void Print(const Arg& message, const Arg& arg1)
{
Log(message + ": " + arg1);
}
template <typename Arg, typename... Args>
static void Print(const Arg& message, const Arg& arg1, const Arg& arg2, const Args&... variables)
{
Print(message, arg1 + ", " + arg2, variables...);
}
template <typename Arg, typename... Args>
static void Print2(const Arg& message, const Arg& arg1, const Args&... variables)
{
std::vector<Arg> args = { variables... };
Arg result = std::accumulate(args.begin(), args.end(), arg1, [](const Arg& a, const Arg& b) {
return a + ", " + b;});
Log(message + ": " + result);
}
Be aware that this version will create copies of the arguments within the std::vector, unlike the other solution which will not. 请注意,此版本将在std :: vector中创建参数的副本,而不像其他解决方案那样。
Both examples can be used in the following fashion: 这两个示例都可以按以下方式使用:
static void Log(const std::string& m)
{
std::cout << m << std::endl;
}
int main()
{
std::string msg = "MyMessage1";
std::string var1 = "Var1";
std::string var2 = "Var2";
std::string var3 = "Var3";
std::string var4 = "Var4";
std::string var5 = "Var5";
Print(msg, var1);
Print(msg, var1, var2);
Print(msg, var1, var2, var3);
Print(msg, var1, var2, var3, var4);
Print(msg, var1, var2, var3, var4, var5);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.