开发者

Lexically-scoped ordering behavior

开发者 https://www.devze.com 2023-01-21 13:33 出处:网络
I have a class with two definitions of ordering.(In the real problem, one is a total order and one is a semiorder.)But it\'s nice to be able to use the comparison operators rather than always having t

I have a class with two definitions of ordering. (In the real problem, one is a total order and one is a semiorder.) But it's nice to be able to use the comparison operators rather than always having to use an explicit comparison function or functor object. So I figured I'd provide some comparison operators like this:

class C;

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

Operators for >, <=, >= are also defined of course, but that's not the point. Now a user can say using namespace Order1; or ... Order2 at file scope or block scope and get the requested behavior for the rest of that file/block.

The disappointing part, which I'd like to improve if possible, is that these usings can't nest.

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.
  }
}

Since using-directives don't hide anything when used in the same namespace, this doesn't provide a way to nicely temporarily reverse the meaning of the operators for a block scope.

Another related idea would be to allow dummy objects on the stack whose constructors and destructors manipulate the "current setting" for which behavior to use. But I don't think I want to head that way for this situation, since that would mean the equivalent of f above could change the behavior of other functions called like g.

Is there another way to get a similar effect but allowing nested operations with the innermost block "hiding" the others? Or am I stuck with one behavior of overloaded operators per declarative region? Which I guess is manageable, since code can still explicitly use a function or functor instead of using the operators.


I would stick with ordinary comparison functions. The rest of the code will be cleaner. No using namespace... or explicit calls to scoped operator<. Reads easier this way, IMO...

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


instead of using namespace Order2 put in

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

which will work in this instance. If you want to "meta-program", i.e. be able to pass in Order1 / Order2 as a template parameter you should make them structs (or classes) with operator< static. then you can do T::operator<(x, y) where T is either Order1 or Order2.


Why don't you scrap the namespaces, and just declare two overloads of operator < with different argument types, one for each class type?

UPDATE

As dgnorton has pointed out in a comment below, you have one class, with two different orderings defined on it. This does seem like a possible cause of problems. Is it possible to split this into two different classes?

0

精彩评论

暂无评论...
验证码 换一张
取 消