这里应用了哪个重载决议规则?
Which overload resolution rule applied here?
我想知道这里应用了哪个重载方法解析规则。
我的目的是使用复制构造函数创建一个新的临时实例,
然后将该对象传递给方法,因此传递 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;
}
重载参考文档看了好几遍,
但对我来说一半清楚
https://en.cppreference.com/w/cpp/language/overload_resolution
看来收集了一组候选方法后,
编译器根据匹配优先级决定哪个方法最匹配。
所以很明显,如果有一些方法接受 std::initializer_list<Kdy>
作为参数,那么这些方法就会被选中。 (我已经测试过了)
那时还是一头雾水
如果精确签名匹配失败,
在这种情况下应用了哪个决议超载规则?
是什么让 compile think match {kdy2}
最适合 const Kdy&
而不是 Kdy&&
?
另外,为什么 { { { kdy2 } } }
不能解释为 Kdy(Kdy&&)
?
请说明这个可怜的家伙。
谢谢!
以下部分标准供参考:
- (3.7) Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution.
- (3.9) Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element ...
第 (3.9) 节解释了为什么 DoAction({kdy2})
select 重载 DoAction(const Kdy&)
。初始化列表的单个元素是 Kdy
类型的左值,并且 DoAction
的两个重载中只有一个可以绑定到左值; selected.
在 DoAction({ {kdy2} })
中,初始值设定项没有 Kdy
类型的单个元素,不使用 (3.9) 并且为 {{kdy2}}
引入了纯右值。通过 (3.7) 考虑 Kdy
的构造函数。候选人是 Kdy(Kdy&&)
和 Kdy(Kdy const&)
。
为了select最好的,{kdy}
被尝试转换为ctors的参数并再次应用(3.9)selected构造函数是副本演员。然后将纯右值绑定到 DoAction
的参数,并且从这些重载来看 DoAction(Kdy&&)
是更好的匹配。
对于 DoAction({ { {kdy2} } })
的尝试与第二种情况相同,但是当尝试将 {{kdy2}}
转换为构造函数的参数时失败,因为初始化列表没有类型的单个元素Kdy
和 (3.7) 不适用。
我想知道这里应用了哪个重载方法解析规则。
我的目的是使用复制构造函数创建一个新的临时实例, 然后将该对象传递给方法,因此传递 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;
}
重载参考文档看了好几遍, 但对我来说一半清楚 https://en.cppreference.com/w/cpp/language/overload_resolution
看来收集了一组候选方法后, 编译器根据匹配优先级决定哪个方法最匹配。
所以很明显,如果有一些方法接受 std::initializer_list<Kdy>
作为参数,那么这些方法就会被选中。 (我已经测试过了)
那时还是一头雾水
如果精确签名匹配失败,
在这种情况下应用了哪个决议超载规则?
是什么让 compile think match {kdy2}
最适合 const Kdy&
而不是 Kdy&&
?
另外,为什么 { { { kdy2 } } }
不能解释为 Kdy(Kdy&&)
?
请说明这个可怜的家伙。 谢谢!
以下部分标准供参考:
- (3.7) Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution.
- (3.9) Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element ...
第 (3.9) 节解释了为什么 DoAction({kdy2})
select 重载 DoAction(const Kdy&)
。初始化列表的单个元素是 Kdy
类型的左值,并且 DoAction
的两个重载中只有一个可以绑定到左值; selected.
在 DoAction({ {kdy2} })
中,初始值设定项没有 Kdy
类型的单个元素,不使用 (3.9) 并且为 {{kdy2}}
引入了纯右值。通过 (3.7) 考虑 Kdy
的构造函数。候选人是 Kdy(Kdy&&)
和 Kdy(Kdy const&)
。
为了select最好的,{kdy}
被尝试转换为ctors的参数并再次应用(3.9)selected构造函数是副本演员。然后将纯右值绑定到 DoAction
的参数,并且从这些重载来看 DoAction(Kdy&&)
是更好的匹配。
对于 DoAction({ { {kdy2} } })
的尝试与第二种情况相同,但是当尝试将 {{kdy2}}
转换为构造函数的参数时失败,因为初始化列表没有类型的单个元素Kdy
和 (3.7) 不适用。