Как сделать рекурсивную лямбда-функцию, которая принимает 2 аргумента, а не 1? - PullRequest
0 голосов
/ 05 марта 2019

Я уже знаю, как создать рекурсивную лямбда-функцию, которая принимает один аргумент, такой как вычисление факториала числа, но я пытаюсь сделать рекурсивную степенную функцию с использованием лямбда-выражения (на практике), но использование двух аргументов в функции вызвало ошибки

это код:

std::function <int(int)> power = [&](int a, int n)
{
    return (n<=1) ? a : a*power(a, n-1);
};

эта строка return (n<=1) ? a : a*power(a, n-1); дает следующие ошибки:

error:   no match for call to '(std::function<int(int)>) (int&, int)'
note:   candidate: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}]
note:   candidate expects 1 argument, 2 provided

Ответы [ 3 ]

0 голосов
/ 05 марта 2019

Вам нужно будет использовать

std::function <int(int, int)> power = [&](int a, int n) { ... }

, чтобы функция работала с двумя аргументами.

Рекомендации по улучшению:

Убедитесь, что вы имеете дело с n = 0 правильно.

Использование

return (n <= 1) ? a : a*power(a, n-1);

не правильно.Вы получите a, когда функция будет вызвана с помощью n = 0.

Использовать

return (n == 0) ? 1 : a*power(a, n-1);

Использовать unsigned int для n.

std::function <int(int, unsigned int)> power = [&](int a, unsigned int n) { ... }

Тогда вам не придется беспокоиться о вызове функции с отрицательными значениями для n.


Завершение функции

std::function <int(int, unsigned int)> power = [&](int a, unsigned int n)
{
    return (n == 0) ? 1 : a*power(a, n-1);
};
0 голосов
/ 05 марта 2019

Ваша рекурсивная лямбда сталкивается с проблемой;для этого требуется точная переменная, в которой он был создан, или UB, чтобы вызвать его.

auto ycomb = [](auto&&f){ return [f=f](auto&&...args){ return f(f, decltype(args)(args)...); }; };

эта маленькая игрушка исправляет эту ошибку.

auto power = ycomb( [](auto&& self, int a, unsigned int n)->int
{
  return (n==0) ? 1 : a*self(self, a, n-1);
});

там.

ycomb - это ycombinator.Он знаменит.

Этот power можно скопировать и безопасно пережить сферу его строительства.

Если вам не нравится self(self, args...), вы можете использовать ycombinator, чтобы сделать его:

auto ycomb0 = [](auto&&f){
  return [=](auto&&...args){
    return f(f, decltype(args)(args)...);
  };
};
auto ycombx_ref = [](auto&& r, auto&& f) {
    return [&r, f](auto&&...args) {
        return f( r(r, f), decltype(args)(args)... );
    };
};
auto ycomb = ycomb0( ycombx_ref );

и теперь self, переданный лямбде, сам по себе не нуждается в передаче самостоятельно:

auto power = ycomb( [](auto&& self, int a, unsigned int n)->int
{
  return (n==0) ? 1 : a*self(a, n-1);
});

Пример в реальном времени .

0 голосов
/ 05 марта 2019

Может быть

std::function <int(int, int)> power = [&](int a, int n) ....
// ...................^^^^^

?

Я имею в виду: если power - это std::function, который инициализируется лямбда-выражением, получающим два целых числа, иis использует в качестве функционала, который получает два целых числа, возможно, имеет место объявить его получающим два целых числа, а не только одно.

...