【问题标题】:How to convert variadic function arguments to array?如何将可变参数函数参数转换为数组?
【发布时间】:2021-09-08 17:13:49
【问题描述】:

如何将可变参数函数参数转换为数组? 我需要这样的东西:

template <typename T>
struct Colordata
{
public:
    T dataFirst;
    T dataLast;

    template <typename... Ta>
    Colordata(Ta... args)
    {
        constexpr std::size_t n = sizeof...(Ta);
        std::cout << n << std::endl;
        dataFirst = (args..)[0];
        dataLast = (args...)[n - 1];
        return;
    }   
};

int main(int argc, char const *argv[])
{
    auto a = Colordata<float>(1.0f, 2.2f, 3.3f, 4.3f, 5.5f);
    return 0;
}

我尝试使用可变参数作为 T args, ... 并使用来自 stdarg.h 的函数,但我无法获得参数的数量。

【问题讨论】:

  • 变量包不能像数组一样被索引。但是,您可以提取特定元素,尽管它需要一些模板工作,因为您需要扩展可变参数包并检索第 N 个条目
  • 从您的类的编写方式来看,您似乎只想获取可变参数包的第一个和最后一个元素。如果是这样,请编辑您的问题以准确地说出来。在这种情况下,将参数放入数组是一个 XY 问题。
  • 另请注意,一个包的每个参数可以有不同的类型。当您执行Colordata&lt;float&gt; 时,您只是在指定第一个参数的类型。其余的由编译器推导出来。在这种情况下,它们都是floats。
  • 我认为 OP 真正需要的是 std::initializer_list&lt;float&gt;,而不是可变参数数组......但由于不清楚他们在做什么,所以很难给出好的建议。

标签: c++ variadic-templates


【解决方案1】:

您不能将参数包转换为数组。您可以从一个数组创建一个数组,但这会复制,这将是一种浪费。相反,我们可以将参数包“转换”为引用的tuple,然后使用get 索引该元组。看起来像

template <typename... Ta>
Colordata(Ta... args)
{
    constexpr std::size_t n = sizeof...(Ta);
    static_assert(n >= 1, "must pass at least one argument");
    std::cout << n << std::endl;
    auto& tuple = std::tie(args...);
    dataFirst = std::get<0>(tuple)
    dataLast = std::get<n - 1>(tuple);
}  

【讨论】:

  • 我认为 OP 真正需要的是 std::initializer_list&lt;float&gt;,而不是可变参数数组......但由于不清楚他们在做什么,所以很难给出好的建议。
  • @MooingDuck 就是这样。我假设正在发生更复杂的事情,因为采用任意数量的参数但只使用 2 没有多大意义。
  • @MooingDuck 好的。我只是想看一个如何使用可变参数的示例。在 c++ 中,我第一次使用这些参数。在我使用可变参数的前一种语言中,动态数组是动态数组,而这个需要比静态数组更大的内存。我想创建一个新的 &T[n] 数组。使用参数。最好的方法是什么?
  • 谢谢。如何将std::get 与变量一起使用?我试过:` std::get(tuple);` 其中 i 是 for 循环上的索引
  • @WusikiJeronii 由于get 使用模板参数,您传递给它的值必须是编译时间常数,i 不是。如果您尝试做一些与您在此处提出的不同的事情,您应该提出一个新问题。
【解决方案2】:

从对构造函数的参数所做的事情来看,似乎不需要数组或以任何方式存储参数。如果您只需要第一个和最后一个参数,您可以编写分别执行这些操作的函数。

获取第一个参数很简单

template <typename First, typename... Ts>
auto first_arg(First const & first, Ts const & ...)
{
  return first;
} 

获取最后一个参数只是稍微复杂一些,但可以通过基本情况重载来完成

template <typename Last>
auto last_arg(Last const & last)
{
  return last;
} 

template <typename First, typename... Ts>
auto last_arg(First const &, Ts const & ... ts)
{
  return last_arg(ts...);
} 

您现在可以在需要的其他地方重用这些函数,并且在您编写的构造函数中,您可以这样做

template <typename... Tas>
Colordata(Ts... args)
{
  dataFirst = first_arg(args...);
  dataLast = last_arg(args...);
}

【讨论】:

  • 不能使用template &lt;typename FirstT, typename LastT, typename... Tas&gt; Colordata(FirstT first, Ts... args, LastT last) {吗?我必须测试才能发现
  • @MooingDuck 不,可变参数必须在函数签名中尾随。
猜你喜欢
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-20
相关资源
最近更新 更多