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

在C++ 11中迭代函子的元组

  •  -1
  • gct  · 技术社区  · 7 年前

    我有一个 std::tuple (未知的)函子,它们都返回相同的类型,所以类似于:

    typedef functor std::function<bool()>;
    std::tuple<functor, functor, functor...> functors;
    

    我想迭代函子,计算每个成员,直到找到一个成功的,否则失败。如何在C++ 11中实现这一点?

    2 回复  |  直到 7 年前
        1
  •  1
  •   max66    7 年前

    不是特别有创意但是…

    如果您创建 foo() 功能如下

    template <typename ... Args>
    bool foo (std::tuple<Args...> const & tf)
     { return bar<0>(tf); }
    

    这个调用从模板索引0开始,下面两个模板(sfinae enabled/disabled)替代函数

    template <std::size_t I, typename ... Args>
    typename std::enable_if<(I >= sizeof...(Args)), bool>::type
       bar (std::tuple<Args...> const &)
     { return false; }
    
    template <std::size_t I, typename ... Args>
    typename std::enable_if<(I < sizeof...(Args)), bool>::type
       bar (std::tuple<Args...> const & tf)
     { return baz(std::get<I>(tf)) || bar<I+1U>(tf); }
    

    还有一个 baz() 调用单个函子的函数

    bool baz (functor const & f)
     { return f(); }
    

    我想你可以得到你想要的东西。

    下面是一个完整的工作示例

    #include <tuple>
    #include <iostream>
    #include <functional>
    
    using functor = std::function<bool()>;
    
    bool baz (functor const & f)
     { return f(); }
    
    template <std::size_t I, typename ... Args>
    typename std::enable_if<(I >= sizeof...(Args)), bool>::type
       bar (std::tuple<Args...> const &)
     { return false; }
    
    template <std::size_t I, typename ... Args>
    typename std::enable_if<(I < sizeof...(Args)), bool>::type
       bar (std::tuple<Args...> const & tf)
     { return baz(std::get<I>(tf)) || bar<I+1U>(tf); }
    
    template <typename ... Args>
    bool foo (std::tuple<Args...> const & tf)
     { return bar<0>(tf); }
    
    bool f0 () { std::cout << "f0 "; return false; }
    bool f1 () { std::cout << "f1 "; return false; }
    bool f2 () { std::cout << "f2 "; return false; }
    bool f3 () { std::cout << "f3 "; return false; }
    bool f4 () { std::cout << "f4 "; return true; }
    bool f5 () { std::cout << "f5 "; return false; }
    bool f6 () { std::cout << "f6 "; return false; }
    bool f7 () { std::cout << "f7 "; return false; }
    bool f8 () { std::cout << "f8 "; return false; }
    bool f9 () { std::cout << "f9 "; return false; }
    
    int main ()
     {
       auto tf = std::make_tuple(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
    
       foo(tf);
     }
    

    显然你可以避免使用 巴兹() 简单地调用函子如下

     return std::get<I>(tf)() || bar<I+1U>(tf);
    

    但是你在 Args... 类型。

        2
  •  -1
  •   Slava    7 年前

    使用合适的容器- std::vector 而不是 std::tuple :

    using functor = std::function<bool()>;
    using functors = std::vector<functor>;
    

    我觉得很明显的是 STD::载体