处理可变参数模板参数包中同一类型的多次出现

问题描述 投票:0回答:1

如何在 C++ 中处理可变参数模板函数以处理模板参数包中同一类型的多次出现,然后将这些参数传递给另一个可变参数函数?

我有以下可变参数模板函数run,它接受多个参数并打印它们:

#include <iostream>

template<typename... Args>
void run(Args... var)
{
    (std::cout << ... << var) << std::endl;
}

我想创建另一个可变参数模板函数processArgs

  1. 处理模板参数包中同一类型的多次出现。
  2. 处理这些参数并为它们分配特定值。
  3. 将收集到的参数传递给 run 函数。

例如,如果我调用 processArgs(),我希望它:

  1. 为参数包中的每种类型创建整型变量、双精度变量等。
  2. 为这些变量分配特定值(例如,为同一类型的每个实例递增值)。
  3. 将这些变量传递给 run 函数,因此它的行为就像调用了 run(42, 3.14, 43, 44, 4.14)

这是期望的结果:

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 函数来实现所描述的行为?

c++ variadic-templates
1个回答
0
投票

这是获得您想要的东西的一种方法。

首先我们从辅助函数开始

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
© www.soinside.com 2019 - 2024. All rights reserved.