我想知道这里应用了哪种重载方法解析规则。
我的目的是使用复制构造函数创建一个新的临时实例,然后将该对象传递给方法,因此r值引用传递。
还有一些重载的方法接受l值,r值,所以我预计r值重载方法会被调用,但它不是。
class Kdy {
public:
Kdy() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Kdy(Kdy&&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Kdy(const Kdy&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void DoAction(const Kdy&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void DoAction(Kdy&&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
}; // Kdy
int main() {
Kdy kdy1;
Kdy kdy2;
// DoAction(const Kdy&), Why??
// kdy1.DoAction(Kdy(kdy2))
kdy1.DoAction({kdy2});
// Then why this works?
// After copy-ctor, DoAction(Kdy&&) was invoked.
kdy1.DoAction({ {kdy2} });
// Then why this dosen't compile?
// Since { {kdy2} } becomes Kdy&&
// { { {kdy2} } } should be Kdy(Kdy&&)
// kdy1.DoAction({ { {kdy2} } });
return 0;
}我已经多次阅读过重载参考文档,但它对我来说几乎是清晰的,分辨率。
似乎在收集了一组候选方法之后,编译器根据它们的匹配优先级来决定哪一种方法最匹配。
因此,很明显,如果有一些方法接受std::initializer_list<Kdy>作为参数,那么这些方法就会被选中。(我测试过了)
如果正确的签名匹配失败了,那么在这个上下文中应用了哪种解析过载规则仍然令人困惑?是什么使编译认为匹配{kdy2}最适合const Kdy&而不是Kdy&&
另外,为什么{ { { kdy2 } } }不能被解释为Kdy(Kdy&&)
请把这个可怜的家伙弄清楚。谢谢!
发布于 2019-01-24 04:37:19
让我们以标准的以下部分为参考:
[dcl.init.list]
第(3.9)节解释为什么DoAction({kdy2})选择重载DoAction(const Kdy&)。初始化程序列表中的单个元素是Kdy类型的lvalue,从DoAction的两个重载中只有一个可以绑定到lvalue;
在DoAction({ {kdy2} })中,初始化器没有一个类型为Kdy的元素,不使用(3.9),并且为{{kdy2}}引入了一个prvalue。(3.7)考虑了Kdy的构造函数。候选人是Kdy(Kdy&&)和Kdy(Kdy const&)。
为了选择最佳的构造函数,尝试将{kdy}转换为ctors的参数,并再次应用(3.9)所选的构造函数复制ctor。然后将prvalue绑定到DoAction的参数,并且从这些重载DoAction(Kdy&&)可以更好地匹配。
对于DoAction({ { {kdy2} } })调度,与第二种情况一样,但是当尝试将{{kdy2}}转换为构造函数的参数时,它会失败,因为初始化程序列表没有一个类型为Kdy的元素,并且(3.7)不适用。
https://stackoverflow.com/questions/54338245
复制相似问题