首页 > 解决方案 > 在 c++11 中迭代函子元组

问题描述

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

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

我想迭代仿函数,评估每个成员,直到找到一个成功的成员,否则失败。如何在 c++11 中实现这一点?

标签: c++c++11stlvariadic-templatestemplate-meta-programming

解决方案


不是特别有创意,但是...

如果foo()按如下方式创建函数

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

该调用,从模板索引 0 开始,以下几个模板(启用/禁用 SFINAE)替代函数

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

显然,您可以避免使用baz()并简单地调用仿函数,如下所示

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

但是您对Args...类型进行了检查。


推荐阅读