C++类构造函数选择优先级问题:为何拷贝构造未被匹配?
问题分析:为何编译器未匹配显式定义的拷贝构造函数
核心原因
在main函数中执行auto b = a;时,编译器没有选择你显式定义的拷贝构造函数A(A const &),反而选中了模板构造函数,本质是函数匹配优先级导致的:
- 模板构造函数
template <typename... Args> A(Args&&... args)属于万能引用,能接受任意类型参数。当传入非const左值a时,模板参数Args会被推导为A&(引用折叠规则:A& &&折叠为A&),实例化出的构造函数签名为A(A&)。 - 显式拷贝构造函数
A(A const &)接受的是const左值引用,而a是非常量左值。此时A(A&)的匹配度更高——无需将非const对象转换为const引用,编译器会优先选择匹配度更优的函数。 - 模板构造函数被选中后,会尝试用
a去初始化成员std::string value,但std::string没有接受A&的构造函数,因此触发编译错误。
解决方案
通过SFINAE机制禁用模板构造函数在拷贝场景下的匹配,让编译器优先选择显式拷贝构造函数:
#include <type_traits> #include <string> struct A { std::string value; A() {} A(A const &) {} template <typename... Args, typename = std::enable_if_t< !std::is_same_v<std::decay_t<std::tuple_element_t<0, std::tuple<Args...>>>, A> >> A(Args&&... args) : value (std::forward<Args>(args)...) {} }; int main(void) { auto a = A(); auto b = a; return 0; }
这段代码通过std::enable_if和std::decay判断,当参数类型衰减后为A时,模板构造函数会被排除,编译器就会选择显式定义的拷贝构造函数。
内容的提问来源于stack exchange,提问作者Vyacheslav Lavrentev
相关产品推荐
相关产品推荐

