分解模板参数包操作

时间:2018-08-21 13:13:56

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

在以下模板函数定义中,我写了两倍的相对长的表达式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))...);
}

出于测试目的,这里是complete program on coliru

3 个答案:

答案 0 :(得分:4)

您可以使用宏。

#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)...);
}

答案 1 :(得分:4)

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。

答案 2 :(得分:1)

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

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)...);
}