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 using
s 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?
精彩评论