繁体   English   中英

乘以可变数量的参数

[英]Multiply variable number of arguments

假设我有一个可变数量的参数,我想将它们相乘。 我想到的第一种方法是递归算法:

template<typename Head>
u64 Multiply(Head head) const
{
    return head;
}

template<typename Head, typename... Tail>
u64 Multiply(Head head, Tail... tail) const
{
    return head * Multiply(tail...);
}

但后来我看到了这个伎俩:

// u32 and u64 are 32 and 64 bit unsigned integers.
template<typename... T>
u64 Multiply(T... args)
{
    u64 res = 1;
    for (const u32& arg: {args...})
        res *= arg;
    return res;
}

第二个看起来对我来说更好。 更容易阅读。 但是,这如何影响性能呢? 有什么东西被复制了? {args...}首先做了什么? 有更好的方法吗?

我可以访问C ++ 14。

编辑要清楚:它是关于运行时乘法,而不是编译时间。

更清楚:我不想有必要计算整数(虽然那是我当前的应用程序),但我发现的算法专门用于整数。

更多:参数属于同一类型。 没有这种限制的算法会非常有趣,但也许是针对不同的问题。

这里有几个问题:

  1. 对性能有什么影响? 不知道。 你需要衡量。 根据参数的类型,我可以想象编译器完全优化事物,但是:它确实知道参数的数量和类型。
  2. 什么是{ args... } 好吧,它为常见的参数类型创建了一个std::initializer_list<T> (假设有一个)。 但是,您可能希望将值与std::common_type_t<T...>而不是使用固定类型。
  3. 有更好的方法吗? 有几种方法虽然我可以想象编译器实际上在这种扩展方面做得很好。 立即想到的另一种选择是return (args * ... * 1); 但是,这需要C ++ 17。 如果存在至少一个参数,则可以省略* 1 :如果存在可变参数的空列表,则可以避免编译时错误。

编码

template<typename... T>
u64 Multiply(T... args)
{
    u64 res = 1;
    for (const u32& size : {args...})
        res *= size;
    return res;
}

对我来说有点神秘:-)为什么我们有类型为T的模板参数,在方法中我们使用了修复大小值? 并且变量名称size看起来非常模糊,因为此var与任何类型的大小无关。 如果将浮点数据提供给模板,则在内部使用整数类型也不是有效的假设。

好的,但要回答你的问题:

第一个可以与您放入模板函数的所有类型一起使用。 第二个使用固定(无符号整数)类型,如果我看到模板本身的声明,这不是我所期望的。

正如我现在所了解的那样,这两个版本都可以成为constexpr :-)并且可以很好地进行编译时计算。

要回答你的评论中的问题:

{args...}

扩展为:

{ 1,2,3,4}

它只是一个“数组”(std :: std :: initializer_list),只有在所有元素具有相同类型时才有效。

所以有

for (const u32& size : {args...})

简单地遍历数组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM