对模板参数包操作进行因素分解

Factor a template parameter pack operation

本文关键字:分解 操作 参数 包操作      更新时间:2023-10-16

在下面的模板函数定义中,我编写了两倍相对较长的表达式details::transform(std::forward<T>(t))其中t是一个参数包。

我该如何分解它?

auto pack = details::transform(std::forward<T>(t))当然行不通。

template<class ...T>
void f(T&&... t)
{
auto check = (details::transform(std::forward<T>(t)) && ...);
if (check == false) {
return;
}
details::act(details::transform(std::forward<T>(t))...);
}

出于测试目的,这里有一个关于coliru的完整程序。

>有一个可悲的事实要C++。转发可以成为令牌集群。而需要转发的表达越复杂,就越痛苦。

可悲的是,我知道缓解它的唯一方法是使用预处理器......

#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)

有了这个,我们可以重构你的函数,使用 IILE 只生成一次该包:

template<class ...T>
void f(T&&... t)
{
[](auto&&... pack) {
auto check = (FWD(pack) && ...);
if (check == false) {
return;
}
details::act(FWD(pack)...);
}(details::transform(FWD(t))...);
}

这样,每个参数只需调用transform一次。我认为这是最终目标。否则,您可能可以使用预处理器在没有 lambda 的情况下生成更简单的内容。

您可以使用宏。

#define FORWARD_TRANSFORM(type, var) details::transform(std::forward<type>(var))

然后你的函数变成

template<class ...T>
void f(T&&... t)
{
auto check = (FORWARD_TRANSFORM(T, t) && ...);
if (check == false) {
return;
}
details::act(FORWARD_TRANSFORM(T, t)...);
}

你不能那样做。您的两个可变参数表达式扩展到不同的模式。你能做的最好的事情就是这样(没有宏(:

template<class ...T>
void f(T&&... t)
{
using details::transform;
// (T&&)t == std::forward<T>(t);
auto check = (transform((T&&)t) && ...);
if (check == false) {
return;
}
details::act(transform((T&&)t)...);
}