我想从http://code.google.com/p/enhsim编译以下代码行:
enh::eout << enh::setw(26);
gcc出现以下错误:
error: no match for 'operator<<' in 'enh::eout << enh::setw(26)'
但是EnhSimOutput
类(其中enh::eout
是一个实例)确实声明了:
EnhSimOutput& operator<< (setw& p);
如果我实现了一个按值接受对象的操作版本,这个问题就消失了:
EnhSimOutput& operator<< (setw p);
或者如果我将enh::setw
对象创建为本地对象,即:
enh::setw wValue(26);
enh::eout << wValue;
我的问题是:为什么gcc不选择运营商的“按引用”版本开始?
编写此代码的开发人员明确地将其编译,但默认gcc拒绝执行此操作。为什么单独声明为局部变量的对象与本地创建的内联?
之间存在差异答案 0 :(得分:13)
值enh::setw(26);
是 rvalue 。实际上,像这样的临时工具是价值。 Rvalues有特殊属性。其中一个是他们的地址不能被采用(&enh::setw(26);
是非法的),并且他们通常不能绑定到非const的引用(一些临时的可以绑定到引用非const,但这些经历了特殊规则:在临时对象上调用成员函数并通过引用非const来捕获异常对象。在后一种情况下,临时甚至是左值)。
有两种表达方式:左值表示对象(进而可以存储值)或函数,右值表示读出的值一个对象或由临时对象,数字文字和枚举器常量表示。在C ++ 03中,为了能够将这些值传递给接受其引用值的函数,有一条规则可以通过引用接受它们:setw const& p
会接受它。也就是说,您必须像这样声明您的运算符:
EnhSimOutput& operator<< (setw const& p);
这有点不幸,因为你无法消除常量左值(使用const enh::setw e(26);
在堆栈上创建的对象)和非const或const rvalues(如enh::setw(26);
非歧义的歧义 - 临时)。此外,如果你这样做,参数不能在其上调用非const成员函数,因为它是一个const的引用。出于这个原因,下一个C ++版本的C ++ 1x引入了一种新的引用,即所谓的 rvalue-references ,它修复了这一点。
Microsoft Visual C ++ 编译器将rvalues绑定到对非const的引用,但在执行此操作时会发出警告(您必须至少使用警告级别4才能显示它)。这是不幸的,因为当移植到标准合规性更严格的其他编译器时问题会增加。
答案 1 :(得分:3)
我的猜测是EnhSimOutput& operator<< (setw& p);
通过非const引用,但值26是“const”,因为它无法修改。尝试将其设置为EnhSimOutput& operator<< (const setw& p);
或尝试
int nNumber = 26;
enh::eout << enh::setw(nNumber);