问题描述
我用 C++ 实现了 lambda 演算,但现在我不知道如何摆脱它。我想测试我的函数是否返回正确的东西,但我无法比较结果,因为它是一个函数。有谁知道我如何测试我的代码?
#include <functional>
class function :
public std::function<function (function)> {
public: using type =
std::function<function (function)>;
public: using type::function;
};
function True = [](function x) {
return [&](function y) {
return x;
};
};
function False = [](function x) {
return [&](function y) {
return y;
};
};
function If = [](function x) {
return [&](function y) {
return [&](function z) {
return x(y)(z);
};
};
};
function And = [](function x) {
return [&](function y) {
return x(y)(x);
};
};
function Or = [](function x) {
return [&](function y) {
return x(x)(y);
};
};
// ...
int main()
{
// ?
}
解决方法
我用以下测试代码解决了我的问题。
#include <cassert>
#include <exception>
template <typename E,typename F>
bool throws(F f)
try {
f();
return false;
}
catch (E const &) {
return true;
}
auto main() -> int
{
function Null;
assert(throws<std::bad_function_call>([&] { True(Null)(True)(True); }));
assert(throws<std::bad_function_call>([&] { False(True)(Null)(True); }));
}
False
的测试有效,但 True
的测试无效。第一个断言没有通过,我不知道为什么。当我按值而不是按引用 (x
-> [&]
) 捕获 [=]
时,一切正常。
True
的新代码:
function True = [](function x) {
return [=](function y) {
return x;
};
};
有谁知道如果我按引用捕获它为什么不起作用?
,我的代码现在看起来像这样(我只是用 [&]
替换了所有的 [=]
并使用了私有继承):
class function :
private std::function<function (function)> {
public: using type =
std::function<function (function)>;
public: using type::function;
public: using type::operator();
public: using type::operator bool;
};
function True = [](function t) {
return [=](function f) {
return t;
};
};
function False = [](function t) {
return [=](function f) {
return f;
};
};
function If = [](function x) {
return [=](function t) {
return [=](function f) {
return x(t)(f);
};
};
};
function And = [](function x) {
return [=](function y) {
return x(y)(x);
};
};
function Or = [](function x) {
return [=](function y) {
return x(x)(y);
};
};
测试如下所示:
auto main() -> int
{
function Null;
assert( True(True)(Null));
assert(!True(Null)(True));
assert( False(Null)(True));
assert(!False(True)(Null));
assert( If(True )(True)(Null));
assert(!If(True )(Null)(True));
assert( If(False)(Null)(True));
assert(!If(False)(True)(Null));
assert(And(False)(False) (Null)(True));
assert(And(False)(True ) (Null)(True));
assert(And(True )(False) (Null)(True));
assert(And(True )(True ) (True)(Null));
assert(Or(False)(False) (Null)(True));
assert(Or(False)(True ) (True)(Null));
assert(Or(True )(False) (True)(Null));
assert(Or(True )(True ) (True)(Null));
}