лямбда с шаблонами - PullRequest
       12

лямбда с шаблонами

5 голосов
/ 06 октября 2011

В настоящее время я делаю упражнения с шаблонными функциями. У меня была задача написать реализацию алгоритма преобразования. Я сделал это следующим образом, и это работает:

template <class in, class out, class T>
out stransform(in b, in e, out d, T p(const T&)) {
    while (b != e) 
        *d++ = p(*b++);
    return d;
}

Как и в случае обычного преобразования, я должен вызывать предикат с явным типом, таким как

stransform(begin(vec1), end(vec1), back_inserter(vec2), predi<double>);

Теперь я наткнулся на лямбды C ++ 11 и хотел вызвать мою функцию следующим образом:

stransform(begin(vec1), end(vec1), back_inserter(vec2), [] (double x) ->double {return x * 10;} );

При этом я получаю ошибку компилятора, что тип не может быть выведен. Это то, чего я не понимаю, так как я в действительности определяю тип Т в своей лямбде дважды.

Я также проверил исходную функцию преобразования, с которой она работает. Затем я проверил реализацию этой и, очевидно, она реализована с помощью шаблона класса для всей функции. Это правильный способ реализации предикатов с помощью шаблонов?

Ответы [ 3 ]

13 голосов
/ 06 октября 2011

Предикат обычно является простым аргументом шаблона:

template <class in, class out, class UnaryPredicate>
out stransform(in b, in e, out d, UnaryPredicate p); 

Это будет принимать указатели на функции, лямбды и функциональные объекты.

2 голосов
/ 06 октября 2011

это, очевидно, реализовано с помощью шаблона класса для всей функции

Небольшое отступление для правильной терминологии: std::transform - это функция шаблон , а не функция. Что еще более важно, в декларации стиля

template<class InputIterator, class OutputIterator, class Functor>
OutputIterator
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f);

параметры шаблона InputIterator, OutputIterator и Functor не обязательно должны быть типами классов. Рассмотрим этот пример:

// function declaration
int increment(int);

int array[] = { 0, 1, 2, 3, 4 };
transform(std::begin(array), std::end(array), std::begin(array), increment);

Тогда InputIterator и OutputIterator выводятся как int*, а Functor - это int(*)(int), , ни один из которых не является типом класса - гораздо меньше шаблонного класса, но я отвлекся. И на самом деле, transform может быть также объявлено

template<typename InputIterator, typename OutputIterator, typename Functor>
OutputIterator
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f);

где ключевое слово typename немного более понятно о природе параметров шаблона: они являются типами любой природы.

2 голосов
/ 06 октября 2011

T p(const T&) - это тип функции, которая принимает T по ссылке . Ваша лямбда получает аргумент значение .

stransform (
    begin (vec1),
    end (vec1),
    back_inserter (vec2),
    [] (const double & x) -> double {
        return x * 10;
    });

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...