关于运算符重载和参数相关查找,Visual Studio 10 和 GCC 4.5 之间的哪个编译器是正确的?
我有以下代码:
class Foo;
class Bar;
class Bar {
public:
Bar() {
}
Bar(Foo &foo) {
}
};
class Foo {
public:
Foo() {
}
Foo(Foo &foo) {
}
Foo(const Bar &bar) {
}
};
Bar operator >> (const Bar &left, const Bar &right) { return Bar(); }
Foo a;
Foo b;
Foo c = a >> b;
在 Visual Studio 10 中,上述代码可以正常编译:编译器识别出 Bar
可以从 Foo&
实例化,因此它调用适当的 < code>operator >>,然后返回一个 Bar
实例,并且构造函数 Foo(const Bar &)
被适当地调用。
然而,GCC 4.5 不编译上述代码。它输出以下错误:
error: no matching function for call to 'Foo::Foo(Foo)'
note: candidates are: Foo::Foo(const Bar&)
note: Foo::Foo(Foo&)
note: Foo::Foo()
根据语言标准,为什么会发生上述情况以及哪个编译器是正确的?
编辑:
为什么 C++ 由于 c = a >>> 创建一个临时
,既然 Foo
对象bFoo(const Bar &)
存在?
I have the following code:
class Foo;
class Bar;
class Bar {
public:
Bar() {
}
Bar(Foo &foo) {
}
};
class Foo {
public:
Foo() {
}
Foo(Foo &foo) {
}
Foo(const Bar &bar) {
}
};
Bar operator >> (const Bar &left, const Bar &right) { return Bar(); }
Foo a;
Foo b;
Foo c = a >> b;
In Visual Studio 10, the above code compiles fine: the compiler recognizes that Bar
can be instantiated from Foo&
, and therefore it invokes the appropriate operator >>
, which then returns a Bar
instance, and the constructor Foo(const Bar &)
is appropriately invoked.
However, GCC 4.5 does not compile the above code. It outputs the following error:
error: no matching function for call to 'Foo::Foo(Foo)'
note: candidates are: Foo::Foo(const Bar&)
note: Foo::Foo(Foo&)
note: Foo::Foo()
Why does the above happen and which compiler is correct, according to the language standard?
EDIT:
Why does C++ create a temporary Foo
object as a result of c = a >> b
, since Foo(const Bar &)
exists?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这与重载或参数查找无关。通过定义
Foo(Foo&)
,您已禁用默认复制构造函数Foo(const Foo&)
的生成,该构造函数是初始化c< 所必需的/code> 来自右值。添加带有 Foo(const Foo&) 签名的 ctor,您的代码将正常运行。我不知道为什么 VS10 会编译这个,但我会尝试查找指定为什么它不应该发生的子句。
我们开始:
§12.8(1) 指定类 X 的非模板构造函数是复制构造函数,如果其第一个参数的类型为 X&、const X&、volatile X&或 const 易失性 X&并且没有其他参数或所有其他参数都有默认值。
§12.8(5) 说,如果我们没有为 X 定义复制构造函数(以上述任何形式),编译器将以 X(const X&) 的形式定义复制构造函数。
因此,定义 Foo(Foo&) 定义了一个复制构造函数,因此编译器不能再隐式定义 Foo(const Foo&) 了。
This has nothing to do with overloading or argument lookup. By defining
Foo(Foo&)
, you've disabled the generation of the default copy constructorFoo(const Foo&)
, which is required to initializec
from an rvalue. Add a ctor with the Foo(const Foo&) signature and your code will run fine. I don't know why VS10 compiles this, but I will try to look up the clauses which specify why it shouldn't happen.Here we go:
§12.8(1) specifies that a non template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X& and there are no other parameters or all other parameters have default values.
§12.8(5) says, that if we don't define a copy constructor for X (in any of the above mentioned forms), the compiler defines a copy constructor in the form X(const X&).
Thus defining Foo(Foo&) defines a copy constructor, so the compiler can't implicitly define Foo(const Foo&) anymore.
这应该有效:
此初始化语法:
被解释为
复制初始化,并且需要一个接受
const Foo&
的可访问复制构造函数。来自标准的
[dcl.init]
部分(来自 C++0x 的措辞):T x{a}
语法是 C++0x 中的新语法,所有其他规则与 C++03 相同。然后适用以下规则(同一部分):
This should work:
This initialization syntax:
Is interpreted as
is copy-initialization and requires an accessible copy-constructor which accepts
const Foo&
.From section
[dcl.init]
of the standard (wording from C++0x):The
T x{a}
syntax is new in C++0x, all the other rules are unchanged from C++03.Then the following rules apply (same section):