我最近读过有关按合同设计的内容,我想通过项目尝试使用它。当我尝试自己想出一些简单的解决方案时,我想到的第一件事就是这个:
#include <iostream>
using namespace std;
template <typename Type>
class Positive {
Type value;
public:
Positive(
Type positive
) :
value(positive)
{
if (!condition())
errorAction();
}
Positive(
const Positive& positive
) :
value(positive.value)
{} // no need to check since variable HAS to respect the contract
Positive(
const Positive&& positive
) :
value(positive.value)
{} // no need to check since variable HAS to respect the contract
Positive& operator=(
const Positive& positive
) {
value = positive.value;
return *this;
}
Positive& operator=(
const Positive&& positive
) {
value = positive.value;
return *this;
}
operator Type() {
return value;
}
private:
bool condition() {
return value > 0;
}
void errorAction() {
cout << "not positive value: " << value << endl;
exit(-1);
}
};
// contract: both inputs and output are positive
template <typename Type>
Positive<Type> minusPositive(
Positive<Type> x,
Positive<Type> y
) {
return x - y;
}
int main() {
int x = 10;
int y = 20;
int z = minusPositive<Type>(x, y); // should fails since x-y <= 0
cout << "Should never display this: " << z << endl;
return 0;
}
它基本上使用隐式转换(构造函数)来启动负责检查契约的包装器和显式转换运算符以返回它。我认为它会很好用 - 参数会被自动包装和检查,而内部函数会自动解包内容。与返回参数类似。我喜欢这个想法,因为合约将在一个地方定义和检查(参数/返回值),方法体将没有额外的行。
但是我会讨论所有会发生的问题 - 我很可能不得不重载=运算符和可能的移动运算符,代码本身将非常灵活(每个合同都必须有自己独立的实现,我不确定模板是否有帮助),更不用说构造函数中的合同失败问题(我应该如何处理它?不检查其中的任何合同或当场终止程序?)。
我查了一些关于它的文章:
您是否知道任何方法/库可以产生干净,可读的代码,在定义每个新合同时不需要额外的大量工作?一些稳定和成熟的东西,最好是已经在Debian 7.3上可用而不编译大量的外部库,也没有添加几个新的存储库/ pinnings?
或者,您是否认为我最初提出的方法可以修复到实际有用的地步?
修改
要使这个问题不是一个偏离主题的话:使用与定义合同类似定义的类是否安全?会不会有一些陷阱,如果有的话,可以通过我使用这些课程或我实施它们的方式来避免吗?