假设我的集合中有自定义类型,并且只有在某些属性上所有项目具有相同值时才设置/排序...如果插入了具有不同值的项目,则模型被搞砸了想保护这个。
我想也许比较函数可能是我们可以测试它(作为断言或异常)的地方,以标记问题和/或防止项目被插入。例如,在TypeName上,如果重要属性不相等,则运算符<()始终返回false。
这是否合理?
答案 0 :(得分:6)
我想把它放在比较器中可能会有问题,因为当你要调用它时你没有得到任何保证。也许一些神话般的实现在项目数量较少时将项目存储在列表中,并且直到稍后才调用比较器?
可能最简单的方法是将std::set
包装在执行这些断言的保护性外部类中。
class MySet {
private:
std::set<myFunkyType> myType;
public:
void insert(myFunkyType type) {
assert(!type.isFunky(), "funk violation");
// and so on
}
// all other members other than insertion or mutation just delegate to the
// underlying set
}
答案 1 :(得分:0)
如果您的std::set
是自定义类的实现细节,则应该由您的类的公共成员函数决定,以确保您的集合中未插入无效元素。否则,如果您需要一个数据结构来传递对象集合而不是使用std::map
,请为您的类提供密钥生成函数并将错误检测代码放在那里。
请记住,作为地图键的集合元素在排序方面应该是不可变的;基于可变状态的排序气味不好。
答案 2 :(得分:0)
operator<
这个想法听起来有点可疑。这仅仅意味着这些元素最后排序。对于所有y,x
是iff x<y==false
的最大元素,并且x<x==false
必须始终保持。但如果这对你来说是可以接受的,那就没关系。
答案 3 :(得分:0)
当你在op&lt;你发现你不能建立一个严格的弱序,唯一合理的是抛出异常。任何类型的插入,或op的可能的其他返回&lt;可能会破坏集合的内部约束。
包装是恕我直言并不是必需的,因为包装的insert()的行为可能是相同的(即抛出异常)。
唯一可能使包装更具吸引力的是,您的标准库实现是否足以能够应对投掷比较器的任何不确定性。我怀疑许多标准库实现对该操作的异常安全性很强。