2010-10-21 71 views
0

我有一个有两种排序定义的类。 (在真正的问题中,一个是总顺序,另一个是半顺序。)但是,能够使用比较运算符而不是总是使用显式比较函数或函子对象是很好的。所以,我想我会提供一些比较操作是这样的:词汇范围的排序行为

class C; 

namespace Order1 { 
    bool operator< (const C&, const C&); 
} 
namespace Order2 { 
    bool operator< (const C&, const C&); 
} 

运营商为><=>=也被定义,当然,不过这不是重点。现在,用户可以在文件范围或块范围内说using namespace Order1;或... Order2,并获取该文件/块的其余部分的请求行为。

令人失望的部分,我想尽可能提高,这些using s不能嵌套。在同一个命名空间中使用时

void g(const C&, const C&); 

using namespace Order1; // for most functions in this file 

void f(const C& x, const C& y) { 
    bool test1 = x < y; // Order1 
    { 
    // Would like to switch to Order2 for this block. 
    using namespace Order2; 
    bool test2 = x < y; // Ambiguous overload! 

    g(x, y); // Unaffected by local using-s. 
    } 
} 

由于using -directives不隐瞒任何东西,这并没有提供一种方式来很好地暂时扭转操作符的含义为块范围。

另一个相关的想法是允许堆栈上的构造函数和析构函数操作“当前设置”的虚拟对象,以便使用该行为。但我不认为我想以这种方式来处理这种情况,因为这意味着相当于上面的f可能会改变称为g等其他函数的行为。

是否有另一种方式获得类似的效果,但允许嵌套操作与最内层的块“隐藏”其他?或者我坚持每个声明区域的重载操作符的行为?我认为这是可以管理的,因为代码仍然可以明确地使用函数或仿函数而不是使用操作符。

+3

显式是好的,隐式是坏的。大致。恕我直言。 :-)干杯, – 2010-10-21 14:48:17

+0

我没有提到的一件事是,这是一个已有的类已经有这些运营商,并成千上万的文件使用的变化。所以我坚持提供一个“默认”操作符行为,这大部分都是旧行为。但我想我会推荐使用显式函数或函子的新代码,而不是与操作符混淆。我只希望有些同事能听取建议。 – aschepler 2010-10-21 15:21:46

回答

2

我会坚持普通的比较功能。其余代码将更清洁。否using namespace...或明确调用范围operator<。通过这种方式读取更容易,IMO ...

int main() { 
    bool b = compare1(4, 5); 
    b = compare2(4, 5); 
} 
0

,而不是使用命名空间Order2放在

bool test2 = Order2::operator<(x, y); 

将在这种情况下工作。如果你想要“元程序”,即能够传递Order1/Order2作为模板参数,你应该使它们成为静态的运算符(或类),其运算符为<。那么你可以做T :: operator <(x,y),其中T是Order1或Order2。

+0

如果需要一个更具体的语法,我宁愿用'Order2 :: compare(x,y)<0',或者继承'std :: binary_function'的函子'Order2 :: Comp()' '。我想我只是为了自己的利益而过于懒惰。 – aschepler 2010-10-21 15:02:37

+0

如果你使用一个类,你可以重载operator()。您需要创建该类的“虚拟”实例。然后你使用compareObj(x,y)。 – CashCow 2010-10-22 11:14:10

0

为什么不废弃命名空间,只声明两个重载operator <具有不同的参数类型,每个类类型一个?

UPDATE

由于dgnorton指出在下面评论,你有一类,与上定义了两个不同的排序。这确实看起来像是问题的可能原因。是否可以将它分成两个不同的类?

+0

在他的情况下,类的类型是相同的...他希望同一个操作符的不同行为......这可能不是一个好主意。 – dgnorton 2010-10-21 14:56:01

+0

如果他打算将谓词传递给一个算法或一个std :: set或类似的命令来给出不同的排序,这可能是一个好主意。如果他将地图放入每个名称空间,它可能会自动从该名称空间中拾取运算符,尽管Koenig Lookup表明它可能会首先查找该类的名称空间。 – CashCow 2010-10-22 08:39:12