![](/img/trans.png)
[英]How to overload the operator++ in two different ways for postfix a++ and prefix ++a?
[英]operator++ as both a postfix and prefix doesn't work with clang
我试图写一个既可以用作前缀又可以用作后缀运算符的运算符
#include <iostream>
#include <utility>
struct B {
// ...
};
template<typename ...T>
void operator++(B, T...) {
std::cout << ((sizeof...(T) == 0) ? "prefix" : "postfix") << std::endl;
}
int main() {
B b;
b++;
++b;
}
GCC可以对此进行编译并正常工作,但是c说
main.cpp:9:24:错误:重载后递增运算符的参数必须具有类型'int'(不是'T ...')
void operator++(B, T...) {
谁是对的?
感谢所有帮助我了解GCC行为的人。 我提交了一份新的Clang错误报告:
原始答案:( 未删除,因为它可能包含有用的信息 )
我要说的全部归结为是否将重载的运算符模板视为重载的运算符。 从逻辑上讲,我想不是这样,Clang是错误的:我认为应该首先根据名称和签名兼容性选择模板作为重载解决方案的候选对象,然后实例化,然后(可能)选择。 我的看法是,仅在实例化之后,编译器才应检查结果函数是否具有适当数量的参数。
但这只是我的意见 。 关于后缀operator ++
重载,请参见第13.5.7 / 1节:
“如果函数是具有一个参数的成员函数(应为int类型)或具有两个参数的非成员函数 (其中第二个应为int类型),则它将为对象定义后缀增量运算符++这种类型的“
该标准似乎并未阐明是否应将函数模板视为涉及合法操作员重载签名限制的函数 (至少,我找不到能解决此歧义的句子)。 只要这是真的,就很难给这个问题一个明确的答案,我们只能留下意见 。
但我想提一下问题的另一个相关方面: 一致性 。
尽管问题文本中的代码确实不能在Clang上编译,但是以下代码确实可以:
template<typename... Ts>
int operator + (X x1, Ts... args)
{
return 0;
}
在这两种情况之间,我看不出任何概念上的区别:如果要在实例化之前检查运算符重载的签名,则以上定义也不应编译。 如果不是这种情况,则应该编译问题文本中的代码。
因此,我认为答案是,海湾合作委员会是正确的,还是两者都是错误的。
更新:
正如@JesseGood和@SethCarnegie正确指出的那样,按照14.7 / 4:
“专门化是实例化或显式专门化的类,函数或类成员。”
此外,按照14.6 / 8:
“对于可为其生成有效专业化的模板,不得发布诊断。”
因此,似乎Clang确实是错误的,并且问题文本中的运算符功能模板不会产生任何编译错误 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.