如何在 C++ 中处理可变参数模板函数以处理模板参数包中同一类型的多次出现,然后将这些参数传递给另一个可变参数函数?
我有以下可变参数模板函数run,它接受多个参数并打印它们:
#include <iostream>
template<typename... Args>
void run(Args... var)
{
(std::cout << ... << var) << std::endl;
}
我想创建另一个可变参数模板函数processArgs:
例如,如果我调用 processArgs
这是期望的结果:
int main()
{
processArgs<int, double, int, int, double>();
// Should result in calling: run(42, 3.14, 43, 44, 4.14), i don't care what the numbers are, it's just random
return 0;
}
如何实现这个 processArgs 函数来实现所描述的行为?
这是获得您想要的东西的一种方法。
首先我们从辅助函数开始
template<std::integral T>
T random_start()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<T> dis(1,1000); // use whatever range you want
return dis(gen);
}
template<std::floating_point T>
T random_start()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<T> dis(1.0, 2.0);
return dis(gen);
}
得到一个随机整数或浮点数。 然后我们可以将其利用到以下形式的有状态函数模板中
template<typename T>
T& get_val()
{
static T val = random_start<T>();
return val;
}
此函数为
static T
的 T
中的每个 Args
创建一个 processArgs
。 说到这里,介绍一下processArgs
:
template<typename... Args>
void processArgs()
{
std::tuple<Args...> params{(get_val<Args>()++)...};
std::apply([](auto... args) { run(args...); }, params);
}
我引入了一个元组,然后必须使用
apply
和辅助 lambda 来调用 run
,这可能看起来很奇怪,但是 的“简单”解决方案
template<typename... Args>
void processArgs()
{
run(get_val<Args>()++...);
}
有一个缺陷,即未指定函数参数的计算顺序,通常在 Windows 上从左到右,在 *Nix 上从右到左。 这意味着在某些系统上,当调用函数时,值将按打印顺序“减少”。您可以在这个现场示例中看到这一点。
将这些放在一起我们得到:
template<typename... Args>
void run(Args... var)
{
((std::cout << var << std::endl), ...);
}
template<std::integral T>
T random_start()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<T> dis(1,1000); // use whatever range you want
return dis(gen);
}
template<std::floating_point T>
T random_start()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<T> dis(1.0, 2.0);
return dis(gen);
}
template<typename T>
T& get_val()
{
static T val = random_start<T>();
return val;
}
template<typename... Args>
void processArgs()
{
//run(get_val<Args>()++...);
std::tuple<Args...> params{(get_val<Args>()++)...};
std::apply([](auto... args) { run(args...); }, params);
}
int main()
{
processArgs<int, double, int, int, double>();
}
在这个现场示例中,它给出了
的输出506
1.29876
507
508
2.29876