【问题标题】:Create recursive function argument list from one value and a size从一个值和一个大小创建递归函数参数列表
【发布时间】:2018-02-21 19:48:46
【问题描述】:

我的目的是创建一个大小为 n 的函数参数列表,这样我就可以将它传递给一个使用折叠表达式将值递归相乘的助手。

我对如何将参数列表传递给助手有点困惑。 有没有办法在没有包表达式的情况下创建函数参数列表? 也许通过创建一个数组或元组?

这是我到目前为止的想法。

template<typename T, typename N>
T SmoothStart(const T& t, const N& n) {
    static_assert(std::is_integral_v<N>, "templatized SmoothStart requires type of N to be integral.");
    static_assert(n >= 0, "templatized SmoothStart requires value of N to be non-negative.");

    if constexpr (n == 0) {
        return 1;
    }
    if constexpr (n == 1) {
        return t;
    }
    return SmoothStart_helper((t, ...)); //<-- obviously this doesn't work but it would be awesome to have!
}

template<typename T, typename... Args>
T SmoothStart_helper(Args&&... args) {
    return (args * ...);
}

【问题讨论】:

  • 什么是t?你只想要nt 的副本吗?
  • @Justin 是的,没错。说 n 是 5 我想要一个由 SmoothStart_helper(t,t,t,t,t) 组成的参数列表
  • 我看到的问题是n 是一个运行时间值,但是对于这种解决方案,您需要知道它的编译时间。如果您可以将 n 设为模板 std::size_t 值,一切都会变得更简单。
  • 您可以将SmoothStart 重命名为Power&lt;std::size_t N, typename T&gt;(const T&amp;t)
  • @Jarod42 SmoothStart 是缓动函数系列的一部分(smoothstep 也是其中之一),域与 Power 不同,将其称为 Power 会产生误导。

标签: c++ variadic-templates c++17 fold-expression


【解决方案1】:

首先,如果你想使用折叠表达式,n 必须在编译时知道。如果您将其移至模板参数,获得N 大小的参数包的最简单方法是使用std::make_index_sequence

// The helper has to be first so that the compiler can find SmoothStart_helper().
template<typename T, std::size_t... Is>
T SmoothStart_helper(const T& t, std::index_sequence<Is...>) {
    // You were taking t by value here; I think you might want to still
    // take it by reference

    // Use the comma operator to simply discard the current index and instead
    // yield t. The cast to void is to silence a compiler warning about
    // Is being unused
    return (((void) Is, t) * ...);
}

template<std::size_t N, typename T>
T SmoothStart(const T& t) {
    // std::size_t is unsigned, so no need to check for N >= 0.
    // We also don't need to special case when N == 1. The fold
    // expression handles that case and just returns t
    return SmoothStart_helper(t, std::make_index_sequence<N>{});
}

然后您可以像这样使用它:SmoothStart&lt;N&gt;(myThing);

Godbolt

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多