C ++ 0x: применение функции к нескольким итераторам - PullRequest
2 голосов
/ 14 июня 2011

Я пытаюсь написать функцию, которая отображала бы функцию через несколько итераторов. Это было бы что-то вроде

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 в fun_over_variadic_args должна быть шаблонной, что означает, что она не может быть лямбда-выражением и не может быть объектом локальной функции, что влечет за собой загрязнение глобального пространства имен.

Кто-нибудь знает лучшее решение для этого?
Спасибо

Изменить: Обратите внимание, что я хочу максимально возможную скорость, поэтому предпочтение будет отдаваться решениям, которые сохраняют возможность включения всех вызовов функций.

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! 
}

Разъяснение альтернативного решения Однако использование этого означает, что веселье не может вернуть пустоту

1 Ответ

1 голос
/ 15 июня 2011

Хорошо, учитывая ваше дополнительное описание проблемы, возможно, что-то такое, как это, будет делать:

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, которая берет все эти итераторы.

...