如何使用折叠表达式创建 N 个浮点值数组?

How to create an array of N floats values with fold expression?

提问人:user877329 提问时间:8/5/2023 最后编辑:JeJouser877329 更新时间:8/5/2023 访问量:154

问:

假设以下函数

template<size_t N>
constexpr std::array<float, N> make_ones()
{
    std::array<float, N> ret{};
    for (size_t k = 0; k != N; ++k)
    {
        ret[k] = 1.0f;
    }
    return ret;
}

是否可以用折叠表达式来写? 问题是我没有可以扩展的包。

C++ C++20 函数模板 fold-expression

评论

0赞 Swift - Friday Pie 8/5/2023
不。使用递归模板 -maybe../ 但为什么不呢std::fill
0赞 Davis Herring 8/5/2023
这与折叠表达式无关,只是关于包扩展(以及如何创建包的常见问题)。
0赞 Pepijn Kramer 8/5/2023
@Swift-FridayPie std::fill 自 C++20 起仅为 constexpr
1赞 Pepijn Kramer 8/5/2023
你为什么问?此数组初始化在编译时计算一次(并且非常快)。那么,是什么让你想到折叠表达式呢?(如您已经注意到,这些是针对参数包的)
0赞 Paul Sanders 8/5/2023
在 C++20 或更高版本中,-> 绝对确定数组在编译时被填充(否则编译器错误将随之而来)。constexprconsteval

答:

4赞 JeJo 8/5/2023 #1

是否可以用折叠表达式来写?

中,不是使用折叠表达式,而是使用包扩展以及索引序列,您可以执行以下操作:

template <size_t N>
constexpr std::array<float, N> make_ones()
{
    return []<size_t... Is>(std::index_sequence<Is...>) {
        return std::array<float, sizeof...(Is)>{( static_cast<void>(Is), 1.0f)...};
    }(std::make_index_sequence<N>{});
}

观看 godbolt.org 中的现场演示


对于不支持 C++20 或更高版本的编译器,可以这样做

template <size_t... Is>
constexpr std::array<float, sizeof...(Is)> make_ones_impl(std::index_sequence<Is...>)
{
    return std::array<float, sizeof...(Is)>{(static_cast<void>(Is), 1.0f)...};
}

template<size_t N>
constexpr std::array<float, N> make_ones()
{
    return make_ones_impl(std::make_index_sequence<N>{});
}

评论

1赞 MatG 8/5/2023
值得称赞,但是,嗯,我知道可读性是主观的,但如果我必须审查这个,我会吓坏的。你认为这段代码的意图是明确的吗?
0赞 Paul Sanders 8/5/2023
@MatG 我也会。
1赞 Dmitry 8/5/2023
@MatG 这是类似事情的常见模式。如果你不熟悉模板元编程,你无论如何都无法阅读任何通用代码(无论它多么明确)。你可以看看 Haskel 代码,它是纯粹的外星语言,直到你详细学习它。
0赞 JeJo 8/5/2023
@MatG 请参阅此处的说明:gcc.godbolt.org/z/bGe3M7KG5
1赞 Bob__ 8/5/2023
@MatG 如果更通用一点,它会帮助你识别模式吗?我不知道它在野外有多普遍,但你可以在这里的一些问答和其他在线 cpp 资源中找到它的使用示例。