在运算符重载中使用可变参数模板是否合法?

时间:2016-03-23 15:11:38

标签: c++ templates operator-overloading language-lawyer variadic-templates

我希望能够按照以下方式写一些内容:

struct bar {};

template <typename ... Args>
bar operator+(bar, Args ...)
{}

我刚用clang / gcc检查过,重载的运算符被二进制表达式(a+b)和一元表达式(+a)选中,正如我所料。但是,运算符比正常函数更受限制,例如 - 你不能用三个参数重载operator+()

上述用法是否合法且便携?

编辑为了给出一些上下文,我显然不希望能够定义可变运算符或任何类型的运算符。我对此感兴趣的原因是一个丑陋的黑客:我想使一些运算符变量,以便我可以用其他非变量实现“覆盖”它们。由于变量模板被认为不如函数模板重载规则中的非可变参数模板专用,我可以使用非可变参数覆盖可变参数运算符。是的,它非常可怕:))

2 个答案:

答案 0 :(得分:5)

首先,定义很好,因为存在非空包 1 的有效特化。

现在,特定表达式a+b+a是i.a.转换为operator+(a, b)operator+(a)形式的非成员调用([over.match.oper]/2)。然后,名称查找会找到运算符函数模板,其专业化将成为候选项的一部分。最后,[over.match.oper]/6像往常一样委托重载解决方案:

  

重载解析的候选函数集是。的并集   会员候选人,非会员候选人和内置人员   候选人。 参数列表包含的所有操作数   运营商。候选函数集中的最佳函数是   根据13.3.2和13.3.3选择。

您的代码也将按预期工作,因为重载解析和部分排序将像所有其他人一样尊重操作员功能模板。

1 声明上述一元运算符,除了postfix --++之外,其形式不正确,无需诊断。参看[temp.res]/(8.2)

答案 1 :(得分:3)

该标准在[over.oper]中限制运算符函数的参数数量(以及默认参数的存在):

  

8 - 除下面明确说明的情况外,运算符函数不能有默认参数([dcl.fct.default])。操作者   函数的参数不能超过相应运算符所需的数量,   如本子条款的其余部分所述。

但是,您声明的是运算符函数模板,它没有此类限制。这意味着你的代码很好;使用一元或二元+将转换为带有一个或两个参数的operator+调用,并相应地生成模板的相应实例化。

如果您使用非法数量的参数专门化或显式地实例化运算符函数模板,那将是非法的,因为( [over.oper] ):

  

1 - [...]操作员功能模板的特化也是一个操作员   功能。 [...]

请注意,如果我们编写一个可以用不正确的类型实例化的非变量运算符函数模板,则会获得类似的效果:

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