Is it legal to use variadic templates in operator overloading?

强颜欢笑 提交于 2020-01-30 04:17:30

问题


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:


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




回答2:


The standard restricts the number of arguments (and the presence of default arguments) for operator functions, in [over.oper]:

8 - An operator function cannot have default arguments ([dcl.fct.default]), except where explicitly stated below. Operator functions cannot have more or fewer parameters than the number required for the corresponding operator, as described in the rest of this subclause.

However, what you have declared is an operator function template, which has no such restrictions. This means that your code is fine; the use of unary or binary + will be transformed into a call to operator+ with one or two arguments and an appropriate instantiation of your template will be generated accordingly.

It would be illegal if you were to specialize or explicitly instantiate the operator function template with an illegal number of arguments, since ([over.oper]):

1 - [...] A specialization of an operator function template is also an operator function. [...]


Note that a similar effect obtains if we write a non-variadic operator function template that can be instantiated with incorrect types:

template<class T> int operator+(T, T) { return 0; }  // OK
struct bar {}; template int operator+(bar, bar);     // OK
template int operator+(int, int);                    // Error is here


来源:https://stackoverflow.com/questions/36181895/is-it-legal-to-use-variadic-templates-in-operator-overloading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!