我正在尝试从C ++中的SK combinator calculus实现K组合子。 K组合子是higher-order function,它基本上取值x
,并返回依次取值y
并从中返回x
的内容它。换句话说,
K(x)(y) == x
或循序渐进:
intermediate = K(x)
intermediate(y) == x
将K(x)
视为独立于y
的事物本身的能力至关重要。此外,在y
上调用K(x)
而不调用y
时,无需指定y
的类型。在代码中的某处评估K(x)(y)
后,可以指定#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;
}
的类型。
我正在尝试修复我编写的试图实现K组合器的代码:
error: extraneous template parameter list in template specialization or out-of-line template definition
输出float[] coordinates = {x, y};
。我试过调整模板参数并移动它们无济于事。有谁知道如何解决这个错误?
答案 0 :(得分:8)
Lambdas不能是模板。你可以这样做:
#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;
}
这些被称为通用lambda(从C ++ 14开始存在),基本上就是你想要的。他们的operator()
是每个auto
参数的模板。
答案 1 :(得分:2)
即使你没有C ++ 14,也很有可能 - 只记得lambdas只是functor对象的快捷符号。因此,我们可以创建一个表示中间值的对象:
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 :(得分:1)
您可以通过以下更改“解决”它:
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);
作为一个解释说明,虽然lambdas本身不能被模板化,但是从C ++ 14变量可以,而我正在做的是将K
声明为模板化变量,它恰好发生了变量被声明为lambda对象。