代码之家  ›  专栏  ›  技术社区  ›  YSC

因子A模板参数包操作

  •  3
  • YSC  · 技术社区  · 6 年前

    在下面的模板函数定义中,我编写了两倍相对较长的表达式 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 回复  |  直到 6 年前
        1
  •  4
  •   StoryTeller - Unslander Monica    6 年前

    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
  •  4
  •   NathanOliver    6 年前

    可以使用宏。

    #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)...);
    }
    
        3
  •  1
  •   Rakete1111    6 年前

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

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