шаблоны — Реализация (типизированного) K комбинатора в Stack Overflow

Я пытаюсь реализовать комбинатор K из СК комбинаторное исчисление в C ++. K комбинатор является функция высшего порядка что в основном имеет значение xи возвращает то, что в очереди принимает значение y и возвращается x от него. Другими словами,

K(x)(y) == x

или пошагово:

intermediate = K(x)
intermediate(y) == x

Способность лечить K(x) как вещь в себе, независимая от y, необходимо. Кроме того, нет необходимости указывать тип y когда просто создаешь K(x) без вызова на y, Тип y можно указать один раз K(x)(y) оценивается где-то в коде.

Я пытаюсь исправить написанный мной код, который пытается реализовать комбинатор K:

#include <iostream>

template<class A>
template<class B>
auto K = [](A x) {
return [=](B y) {
return x;
};
};

int main()
{
std::cout << "Hello world!\n";
auto Kx = K<int>(3);
auto Kxy = Kx<float>(4.5);
std::cout << Kxy << std::endl;
}

Выводит error: extraneous template parameter list in template specialization or out-of-line template definition, Я попытался настроить параметры шаблона и переместить их безрезультатно. Кто-нибудь знает, как я мог исправить эту ошибку?

3

Решение

Лямбды не могут быть шаблонами. Вы можете сделать это, хотя:

#include <iostream>

auto K = [](auto x) {
return [=](auto y) {
return x;
};
};

int main()
{
std::cout << "Hello world!\n";
auto Kx = K(3);
auto Kxy = Kx(4.5);
std::cout << Kxy << std::endl;
}

Они называются общими лямбда-выражениями (существуют с C ++ 14) и в основном то, что вы хотите. Их operator() это шаблон для каждого auto параметр.

8

Другие решения

Это вполне возможно, даже если у вас нет C ++ 14 — просто помните, что лямбды — это просто сокращенная запись для объектов функторов. Поэтому мы можем создать объект, представляющий промежуточное значение:

template<class A>
class Intermediate {
A m_a;
public:
explicit Intermediate(const A& a)
: m_a(a)
{}

template<class B>
A operator()(const B&) const
{ return m_a; }
};

template<class A>
Intermediate<A> K(const A& a)
{ return Intermediate<A>(a); }

Отдельный K Функция необходима для вывода аргумента шаблона, чтобы мы могли написать K(x)(y),

2

Вы можете «решить» это следующим изменением:

template<class A, class B>
auto K = [](A x) {
return [=](B y) {
return x;
};
};

Однако затем вам также необходимо изменить вызовы:

auto Kx = K<int, float>(3);
auto Kxy = Kx(4.5);

В качестве пояснительной записки, хотя сами лямбды не могут быть шаблонными, но из C ++ 14 переменные могут, и я делаю декларацию K как шаблонная переменная, так уж получилось, что переменная объявлена ​​как лямбда-объект.

1