如何"duplicate"模板参数包扩展?
How to "duplicate" template parameter pack expansion?
请考虑以下代码:
template < size_t... Indices >
void something(std::index_sequence<Indices...>)
{
// how to obtain the following call where N is sizeof...(Indices)?
// foo(f(0),g(0),f(1),g(1),...,f(N-1),g(N-1));
}
回答以下问题的关键:
// how to obtain the following call where N is sizeof...(Indices)?
// foo(f(0),g(0),f(1),g(1),...,f(N-1),g(N-1));
是制定如何实际生成这样的包扩展。我们有2N
论点,它们会像:
+=====+======+
| idx | expr |
+-----+------+
| 0 | f(0) |
| 1 | g(0) |
| 2 | f(1) |
| 3 | g(1) |
| ....
+=====+======+
在 C++17 中,我们可以用if constexpr
编写这样的表达式:
template <size_t I>
auto expr() {
if constexpr (I % 2 == 0) {
// even indices are fs
return f(I / 2);
} else {
// odds are gs
return g(I / 2);
}
}
它甚至可以是将integral_constant
作为参数的 lambda。所以我们真的只需要把我们N
的参数变成2N
参数,这只是添加更多索引的问题:
template <auto V>
using constant = std::integral_constant<decltype(V), V>;
template < size_t... Indices >
void something(std::index_sequence<Indices...>) {
auto expr = [](auto I) {
if constexpr (I % 2 == 0) {
return f(I / 2);
} else {
return g(I / 2);
}
}
return foo(
expr(constant<Indices>{})..., // 0, ..., N-1
expr(constant<Indices + sizeof...(Indices)>{})... // N, ..., 2N-1
);
}
我能想象到的最好的是使用std::tuple_cat
和std::make_pair
来std::tuple
foo()
的论点。
不幸的是,我只知道如何使用辅助函数来调用foo()
template <typename T, std::size_t... I>
void somethingH (T const & t, std::index_sequence<I...> const &)
{ foo(std::get<I>(t)...); }
template <std::size_t... I>
void something (std::index_sequence<I...> const &)
{
somethingH(std::tuple_cat(std::make_pair(f(I), g(I))...),
std::make_index_sequence<(sizeof...(I) << 1)>{});
}
使用std::apply
(仅从 C++17 开始可用),您可以使用 lambda 函数选择正确的foo
(如 SirGuy 建议的那样;谢谢!)并避免使用辅助函数
template <std::size_t... I>
void something (std::index_sequence<I...> const &)
{
std::apply([](auto && ... as)
{ return foo(std::forward<decltype(as)>(as)...); },
std::tuple_cat(std::make_pair(f(I), g(I))...));
}
以下是完整的 C++17 工作示例
#include <iostream>
#include <utility>
#include <tuple>
int f (std::size_t n)
{ return n; }
int g (std::size_t n)
{ return -n; }
template <typename ... Args>
void foo (Args ... as)
{ (std::cout << ... << as) << std::endl; }
template <std::size_t... I>
void something (std::index_sequence<I...> const &)
{
std::apply([](auto && ... as)
{ return foo(std::forward<decltype(as)>(as)...); },
std::tuple_cat(std::make_pair(f(I), g(I))...));
}
int main()
{
something(std::make_index_sequence<7U>{});
}
相关文章:
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 扩展可变参数模板中的变量名称
- 扩展C++生成的代码的模板参数类型名称
- 将元组类型扩展为可变参数模板?
- 嵌套参数包扩展失败
- 模板参数部分中有关包扩展的一些混淆
- 可变参数模板参数扩展 类型为 std::function 的类成员
- 如何使用 std::forward 精确地评估参数包的扩展?
- 参数包没有扩展'...'即使...被使用
- 将可变参数类型列表的扩展打包为复杂类型的初始值设定项列表 - 合法吗?
- 如何"unzipping"扩展参数包模式?
- 可变参数函数参数包扩展
- c++非类型参数包扩展
- 可变参数模板类扩展
- 模板 使用数据数组调用函数时扩展参数包
- 将代码移出类定义时未扩展参数包
- 在折叠表达式中扩展参数包作为 lambda 捕获的一部分 - gcc 与 clang
- 当可变参数模板类继承自模板参数时,在调用基类型的方法时扩展参数包
- 可变模板包扩展参数id
- 我有一个成员,该成员是指向参数化函数的指针,我可以扩展参数类型吗?