views:

212

answers:

2

I've never quite understood how the argument lists for operator overloading are determined in a systematic way, and I'm particularly confused by a problem I have now.

When you overload a unary operator it has one argument, or zero if it's a class member. When you overload a binary operator it has two arguments, or one if it's a class member. At least that's the way it would seem to work. I'm having a problem with operator new (not a class member) however.

In a codebase I'm working in, as in other places I have seen in the past (like here for example) there is a define like #define new new(__FILE__, __LINE__) and a corresponding function with the signature void *new(size_t size, const char *file, unsigned line) or something like it for memory debugging. I note that the one in my project is actually different from the previously linked one. This presents a problem for me, because for some reason it's messing up a placement new. I've looked in The C++ Programming Language, and if it explains this I'm missing it.

Is new special in this regard, i.e. does it have specific language defined extra debug signatures? It doesn't seem like it because, as I noted above, I've seen slightly different signatures in different places. If it does, what other operators have non-obvious signatures, and what are they? Are these varied signatures instead some implementation specific extras? If so, are there any general rules as to what most implementations do? Alternatively, is it an arity issue like I implied in my title? Can you just tack on as many extra arguments as you want in the signature and if you call new with the arguments between the new keyword itself and the new type you want you can just do whatever? Or am I even more confused, and there's something else I'm missing?

Most importantly in the short term (although I'd really like to understand this), what's going on the messes up my placement new? The macro is causing an expansion something like new ("file.cpp", 100) (class_pointer) class_t. Is the problem the two groups in parenthesis maybe, or something else?

+2  A: 

operator new is closer to functions in that you can provide as many overloads as you want and the compiler will choose the version based on function overload rules.

So, when you do new ((T1)value1, (T2)value2) TYPE, that will get routed to:

operator new(size_t, T1, T2);

The problem with your macro is that it is assuming you are calling the plain version of new and that it can use the preprocessor to turn that into a call to debugging new. The macro is broken when you need to call a different version of new.

If you need to call placement new (or any other special new), you can fix your issue by turning off that macro:

#undef new
R Samuel Klatchko
A: 

The arity of an overloaded operator is whatever you declare. For the operators named after symbols (+), if you define them to have extra args, they will only be invoked via an explicit call. (operator +(a, b, c, d, e)). For operator new, you must give it at least one arg, but you may give it as many as you want. Regular operator overloading determines which one gets called.

bmargulies