我一直在寻找一个示例,展示如何在C ++中实现约束(或者是一个可以让我轻松完成此操作的boost库),但没有太多运气。我能想到的最好的是:
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
template<typename T>
class constrained
{
public:
constrained(boost::function<bool (T)> constraint, T defaultValue, T value = defaultValue)
{
ASSERT(constraint(defaultValue));
ASSERT(constraint(value));
this->value = value;
this->defaultValue = defaultValue;
this->constraint = constraint;
}
void operator=(const T &assignedValue)
{
if(constraint(assignedValue))
value = assignedValue;
}
private:
T value;
T defaultValue;
boost::function<bool (T)> constraint;
};
int main(int argc, char* argv[])
{
constrained<int> foo(boost::lambda::_1 > 0 && boost::lambda::_1 < 100, 5, 10);
foo = 20; // works
foo = -20; // fails
return 0;
}
当然,您可能需要从约束类中获得更多功能。这只是一个起点的想法。
无论如何,我看到的问题是我必须重载T定义的所有运算符,以使其真正表现得像T,并且我无法找出它们是什么。现在,我实际上并不需要那么多不同类型的约束,所以我可以省略模板并硬编码。不过,我想知道是否有一般(或至少更多的冥想/优雅)解决方案,或者我的方法是否有任何严重错误。
答案 0 :(得分:4)
看起来很好的例子。但是一定要实现所有的操作符并处理错误的值。
foo = 100; // works
++foo; // should throw an exception or perform an assert
使用boost operators帮助您解决操作员过载问题。
最好有一个选项作为模板参数:异常或断言。
我会用这样的课。拥有一个自动检查矢量范围并进行断言的索引参数总是更好。
void foo( VectorIndex i );
答案 1 :(得分:3)
您不需要像其他人建议的那样重载所有运算符,尽管这是提供最大控制的方法,因为涉及constrained<T>
类型的对象的表达式将保留此类型。
另一种方法是仅重载变异运算符(=,+ =, - =,* =,/ =,%=,&amp; =,| =,^ =,&lt;&lt; =,&gt;&gt; =,前后++,前后 - )并提供用户定义的转换T
:
template<typename T>
class constrained {
... // As before, plus overloads for all mutating operators
public:
operator T() const {
return value;
}
};
这样,任何涉及constrained<T>
对象的表达式(例如x + y
x
为int
且y
为constrained<int>
)都将是类型T
的右值,通常更方便有效。没有安全性丢失,因为您不需要控制涉及constrained<T>
对象的任何表达式的值 - 您只需要在{{1}时检查约束变成T
,即在constrained<T>
的构造函数和任何变异运算符中。
答案 2 :(得分:2)
我同意Mykola Golubyev的观点,即提升运营商会有所帮助。
您应该为您正在使用的所有类型定义所需的所有运算符。
如果您使用的任何类型不支持运算符(例如运算符++()),则调用此方法的代码将无法编译,但所有其他用法都将编译。
如果要对不同类型使用不同的实现,请使用模板专业化。
答案 3 :(得分:2)
Boost.Constrained_Value可能对您有用。去年12月是reviewed,但它不是最新的Boost版本。 IIRC,审查大多是积极的,但该决定仍未决定。
答案 4 :(得分:1)
我可能只是感到困惑,但是如果你面对必须违反特定约束的参数,那么为它们创建一个类是不是最容易的,检查构造函数和赋值运算符中的约束?
答案 5 :(得分:0)
Boost实际上正在讨论这样一个库(我不知道它变成了什么)。我也编写了我自己的这种类型的版本,行为略有不同(灵活性较差,但更简单)。我在博客中发表了一个公认有点偏见的比较:Constrained vs. restricted value types
编辑:显然Eric更了解促进实施的进展情况。