I would like to be able to write something along these lines:
struct bar {};
template <typename ... Args>
bar operator+(bar, Args ...)
{}
I just checked with clang/gcc and the overloaded operator is picked up both by binary expressions (a+b
) and unary expressions (+a
), as I would expect. However operators are more restricted than normal functions, in the sense that - for instance - you cannot overload operator+()
with three arguments.
Is the usage above legal and portable?
EDIT To give a bit of context, I am clearly not expecting to be able to define variadic operators or anything of the sort. The reason I am interested in this is for a ugly hack: I would like to make some operators variadic so that I can "override" them with other non-variadic implementations. Since variadic templates are considered to be less specialised than non-variadic templates in the function template overloading rules, I could override a variadic operator with a non-variadic one. Yes it's pretty horrid :)
1) Only built-in operators can be overloaded. New operators can not be created. 2) Arity of the operators cannot be changed. 3) Precedence and associativity of the operators cannot be changed.
With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.
MotivationEdit. C++ allows overloading of the unary ampersand (&) operator for class types. The return type of such an operator need not be the actual address of the object. Intentions of such a class are highly debatable, but the language allows it nevertheless.
First off, the definition fine, because there exist valid specializations with non-empty packs1.
Now, specific expressions a+b
or +a
are i.a. transformed into non-member calls of the form operator+(a, b)
and operator+(a)
, respectively ([over.match.oper]/2). Name lookup then finds the operator function template, whose specialization becomes part of the candidates. Finally, [over.match.oper]/6 just delegates to overload resolution as usual:
The set of candidate functions for overload resolution is the union of the member candidates, the non-member candidates, and the built-in candidates. The argument list contains all of the operands of the operator. The best function from the set of candidate functions is selected according to 13.3.2 and 13.3.3.
Your code will also work as intended, since overload resolution and partial ordering will respect the operator function template like all others.
1 declaring the above for unary operators, except perhaps postfix --
and ++
, is ill-formed, no diagnostic required. Cf. [temp.res]/(8.2).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With