【问题标题】:C++0x: applying function over multiple iteratorsC++0x:在多个迭代器上应用函数
【发布时间】:2011-06-14 19:53:40
【问题描述】:

我正在尝试编写一个将函数映射到多个迭代器的函数。它会像

template <class Fun>
fun_over_variadic_args(Fun fun) { }

template <class Fun, class First, class Rest...> 
fun_over_variadic_args(Fun fun, First& first, Rest&... rest) { 
  fun(first); 
  fun_over_variadic_args(fun, rest...);
}

namespace { 
  template <class T> struct thunk_inc { 
    decltype(T::operator++()) operator()(T& t) { return ++t; } 
  }; 
}

template <class Fun, class MainIterator, class RestOfIterators...>
std::tuple<MainIt&, RestOfIts&...> map_over_iterators(Fun fun, MainIt& it, MainIt& end, RestOfIts&... rest) {
const thunk_inc();
for (; it!=end; fun_over_variadic_args(thunk_inc, it, rest...)) {
      // Do something
    }
}

问题出现了,fun_over_variadic_args 中的函数 Fun 需要模板化,这意味着它不能是 lambda,也不能是需要污染全局命名空间的局部函数对象。

有人知道更好的解决方案吗?
谢谢

编辑:请注意,我想要尽可能快的速度,因此首选保留内联所有函数调用可能性的解决方案。

Edit2:刚刚意识到我可以使用匿名命名空间将 Fun 函数的范围限制在一个文件中。如果存在的话,我仍然很想知道一个更简洁的解决方案。

替代解决方案 我发现只要将结果传递给另一个函数,我就可以将函数 fun 应用于可变参数包。所以如果我有一个函数 fun 想应用于每个参数,我可以做类似的事情

template <class... T>
void foo(T... t) { }

template <class... Arg>
void test(Arg... arg) {
  foo(fun(arg)...); // Works!
  fun(arg)...; // Doesn't work! 
}

澄清替代解决方案然而,使用这个意味着 fun 不能返回 void

【问题讨论】:

  • 您能否举例说明您将如何使用它,或者更好地说明您想要实现的目标?
  • @Kerrek SB:fun_over_variadic_args 的具体解决方案将在 map_over_iterators 中使用。一般来说,它可以在需要将函数应用于指定为可变参数的多个值的任何地方使用。
  • @Sid:你介意做一个最小的例子来展示这个对象的实际用途吗?
  • @Kerrek SB:为 map_over_iterators 编写了演示 fun_over_variadic_args 用法的代码
  • 请注意,这可以在 C++03 中通过 boost::zip_iterator + boost::fusion::fused 轻松实现。

标签: templates c++11 variadic-functions variadic-templates


【解决方案1】:

好的,鉴于您对问题的附加描述,也许像这样的可变参数可以:

template <typename ItHead, typename... ItTail>
void advance_iterators(ItHead & it, ItTail ...others)
{
  ++it;
  advance_iterators(others...);
}

template <typename It>
void advance_iterators(ItHead & it)
{
  ++it;
}

template <typename Fun, typename ItMain, typename ...ItOthers>
apply_helper(Fun & f, ItMain it, ItOthers ...others)
{
   f(*it);
   apply_helper(f, others...);
}

template <typename Fun, typename ItMain, typename ...ItOthers>
apply_helper(Fun & f, ItMain it)
{
   f(*it);
}

template <typename Fun, typename ItMain, typename ...ItOthers>
apply (Fun & f, ItMain begin, ItMain end, ItOthers ...others)
{
  while (begin != end)
  {
    apply_helper(f, begin, others...);
    advance_iterators(begin, others...);
  }
}

这里明显的限制是Fun 必须适用于迭代器的所有值类型,并且范围必须相等。函数对象是通过引用传递的,你可以根据自己的喜好来修改。

更新:如果我误解了,并且您希望 f 同时对所有值进行操作,那么您应该摆脱 apply_helper 并调用 f(begin, others...) 并创建一个函数 f这需要所有这些迭代器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 2022-08-02
    • 1970-01-01
    • 2020-08-15
    • 2021-02-26
    相关资源
    最近更新 更多