Упрощение std :: transform для одного вектора - PullRequest
0 голосов
/ 20 октября 2018

Я хочу написать простую функцию, чтобы упростить std::transform для преобразования на одном векторе.

Что у меня так далеко:

template<typename T>
void transform(std::vector<T> &vec, const std::function<T(const T &)> &fun) {
  std::transform(std::begin(vec), std::end(vec), std::begin(vec), fun);
}

Теперь, когда я хочучтобы использовать эту функцию, я могу написать, например:

transform<int>(vec, my_function);

Но я бы предпочел, если бы я мог просто использовать

transform(vec, my_function);

Есть ли способ настроить мой код для автоматического выводатип?

ошибка:

no matching function for call to 'transform' and note: candidate template ignored:
could not match 'function<type-parameter-0-0 (const type-parameter-0-0 &)>' 
against '(lambda at [...]

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

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

using std::begin;
using std::end;

template <class Range, class F>
auto transform(Range&& range, F f)
noexcept(noexcept(std::transform(begin(range), end(range), begin(range), f)))
-> decltype(std::transform(begin(range), end(range), begin(range), f))
{ return std::transform(begin(range), end(range), begin(range), f); }

Да, объект-функция копируется.Если вы не хотите этого, просто передайте std::reference_wrapper, используя std::ref, как для алгоритмов стандартной библиотеки.

0 голосов
/ 20 октября 2018

Еще один способ использования аргумента std::function, если по какой-то причине он вам нужен, - отключить в нем вывод типа для T, переместив T в не выводимый контекст:

template<typename T>
struct Identity { using Type = T; };

template<typename T>
using Id = typename Identity<T>::Type;

template<typename T>
void transform(std::vector<T>&, const std::function<Id<T>(const Id<T>&)>&);
0 голосов
/ 20 октября 2018

Кажется, вы используете лямбду в качестве аргумента;Лямбда может быть преобразована в std::function, но неявное преобразование не будет учитываться при выводе аргумента шаблона , поэтому оно не выполняется.

Вывод типа не учитывает неявные преобразования (кроме корректировок типов, перечисленных выше): это работа для разрешения перегрузки, которая произойдет позже.

Вы можете использовать static_cast явно, чтобы преобразовать лямбду в std::function при ее передаче, или прекратить использованиеstd::function.например,

template<typename T, typename F>
void transform(std::vector<T> &vec, F fun) {
  std::transform(std::begin(vec), std::end(vec), std::begin(vec), fun);
}
...