Widget类定义如下:
class Widget
{
public:
...
size_t weight() const;
size_t maSpeed() const;
...
}
通常情况下,按重量对Widget进行排序是最自然的方式。Widget的operator < 反映了这一点。
bool operator < (const Widget& lhs, const Widget& rhs)
{
return lhs.weight() < rhs.weight();
}
但是在某种情况下,我们需要创建一个按照最大速度进行排序的multiset容器。mutliset的默认比较函数是less,而less在默认情况下会调用operator <来完成自己的工作。
为了让multiset按照最大速度进行排序,一种显而易见的实现方式是:特化less,切断less和operator < 之间的关系,让它只考虑Widget的最大速度:
template<>
struct std::less<Widget> : public std::binary_function<Widget, Widget, bool>
{
bool operator () (const Widget& lhs, const Widget& rhs) const
{
return lhs.maxSpeed() < rhs.maxSpeed();
}
}
operator < 不仅仅是less的默认实现方式,它也是程序员期望less所做的事情,让less不调用operator < 而去做别的事情,这会无端违背程序员的意愿,这与"最小给人惊奇"原则完全背道而驰,应该完全避免。
在STL中,凡是使用了less的地方你都可以指定另外的一个比较类型。然后让它来完成你期望的比较操作:
struct MaxSpeedCompare : public binary_function<Widget, Widget, bool>
{
bool operator () (const Widget& lhs, const Widget& rhs) const
{
return lhs.maxSpeed() < rhs.maxSpeed();
}
}
为了创建新的multiset,使用MaxSpeedCompare作为比较类型,这样就避免使用了默认的比较类型(less):
multiset datas;它创建了一个存放Widget的multiset容器,排序规则由MaxSpeedCompare定义。
相比之下,mutliset datas;说明了datas是一个采用默认排序方式的、存放Widget对象的mutliset容器。这意味着它使用less进行排序,但事实上所有人都会假设它是通过operator <来排序的。
应该尽量避免修改less的行为,因为这样做很可能会误导其他人。如果你使用了less,无论是显示还是隐式,都需要确保它与operator <具有相同的意义。如果你希望以一种特殊的方式来排序对象,那么最好创建一个特殊的函数子类,它的名字不能是less。