您可以在调用站点中交错可变参数吗?
Can you interleave variadic parameters in call sites?
是否可以在函数调用站点内交错模板参数?
我实际上想执行以下操作,但我不知道如何执行(伪代码):
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
static_assert(sizeof...(indices) == sizeof...(Ts));
constexpr n = sizeof...(Ts);
bar(
indices[0], parse<Ts[0]>(things[0]),
indices[1], parse<Ts[1]>(things[1]),
...
indices[n-1], parse<Ts[n-1]>(things[n-1]));
}
注意:我知道可以做到以下几点(伪代码):
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
static_assert(sizeof...(indices) == sizeof...(Ts));
constexpr n = sizeof...(Ts);
bar(
indices[0], indices[1], ..., indices[n-1],
parse<Ts[0]>(things[0]),
parse<Ts[1]>(things[1]),
...
parse<Ts[n-1]>(things[n-1]));
}
我想到的一个部分解决方案是添加一个 swizzling 组件:
template <typename Func>
decltype(auto) swizzle()
{
return Func();
}
template <typename Func, typename T0>
decltype(auto) swizzle(size_t i0, T0 &&t0)
{
return Func(i0, std::forward<T0>(t0));
}
template <typename Func, typename T0, typename T1>
decltype(auto) swizzle(size_t i0, size_t i1, T0 &&t0, T1 &&t1)
{
return Func(i0, std::forward<T0>(t0), i1, std::forward<T1>(t1));
}
但我想我必须手动编写每个我想考虑的案例。
像这样:
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
std::apply([](auto...args) {
bar(args...);
}, std::tuple_cat(std::make_tuple(indices, parse<Ts>(*(things++)))...));
}
如果 bar
是 lambda 而不是函数模板,您可以直接将 bar
作为第一个参数传递给 std::apply
。
如果您想避免复制 parse<Ts>(*(things++))
的 return 值,您可以使用 std::forward_as_tuple
而不是 std::make_tuple
。
如果 *(things++)
让你不舒服,一个稍微冗长的替代方法是使用 std::index_sequence
:
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
[=]<auto... Is>(std::index_sequence<Is...>) {
std::apply([](auto...args) {
bar(args...);
}, std::tuple_cat(std::make_tuple(indices, parse<Ts>(things[Is]))...));
}(std::index_sequence_for<Ts...>());
}
是否可以在函数调用站点内交错模板参数?
我实际上想执行以下操作,但我不知道如何执行(伪代码):
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
static_assert(sizeof...(indices) == sizeof...(Ts));
constexpr n = sizeof...(Ts);
bar(
indices[0], parse<Ts[0]>(things[0]),
indices[1], parse<Ts[1]>(things[1]),
...
indices[n-1], parse<Ts[n-1]>(things[n-1]));
}
注意:我知道可以做到以下几点(伪代码):
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
static_assert(sizeof...(indices) == sizeof...(Ts));
constexpr n = sizeof...(Ts);
bar(
indices[0], indices[1], ..., indices[n-1],
parse<Ts[0]>(things[0]),
parse<Ts[1]>(things[1]),
...
parse<Ts[n-1]>(things[n-1]));
}
我想到的一个部分解决方案是添加一个 swizzling 组件:
template <typename Func>
decltype(auto) swizzle()
{
return Func();
}
template <typename Func, typename T0>
decltype(auto) swizzle(size_t i0, T0 &&t0)
{
return Func(i0, std::forward<T0>(t0));
}
template <typename Func, typename T0, typename T1>
decltype(auto) swizzle(size_t i0, size_t i1, T0 &&t0, T1 &&t1)
{
return Func(i0, std::forward<T0>(t0), i1, std::forward<T1>(t1));
}
但我想我必须手动编写每个我想考虑的案例。
像这样:
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
std::apply([](auto...args) {
bar(args...);
}, std::tuple_cat(std::make_tuple(indices, parse<Ts>(*(things++)))...));
}
如果 bar
是 lambda 而不是函数模板,您可以直接将 bar
作为第一个参数传递给 std::apply
。
如果您想避免复制 parse<Ts>(*(things++))
的 return 值,您可以使用 std::forward_as_tuple
而不是 std::make_tuple
。
如果 *(things++)
让你不舒服,一个稍微冗长的替代方法是使用 std::index_sequence
:
template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
[=]<auto... Is>(std::index_sequence<Is...>) {
std::apply([](auto...args) {
bar(args...);
}, std::tuple_cat(std::make_tuple(indices, parse<Ts>(things[Is]))...));
}(std::index_sequence_for<Ts...>());
}