为何删除拷贝/移动构造函数后仍可跨不同模板类构造对象?
问题原因解析
核心逻辑
你遇到的现象本质是C++隐式转换规则与模板构造函数的结合作用:
合法的隐式转换路径
你的const_Obj<T,N>类定义了非explicit的转换运算符,可以将const_Obj<T,N>隐式转换为Obj<T,N>;同时const_Obj<T,N>提供了模板构造函数,接受任意Obj<U,N>类型的参数。当尝试从
const_Obj<float,1>构造const_Obj<Float,1>时,编译器会匹配这个模板构造函数:- 实参
const_Obj<float,1>只需经过一次用户定义转换(调用转换运算符转为Obj<float,1>),就能满足构造函数的参数类型要求——这完全符合C++隐式转换序列的规则(隐式转换序列允许最多一次用户定义转换)。 - 构造函数内部,
Obj<float,1>中的float类型可以通过隐式转换(比如Float类的非explicit构造函数)转为Float,完成const_Obj<Float,1>的初始化。
- 实参
explicit关键字的作用
当你给Obj的构造函数加上explicit关键字后,会直接打断const_Obj→Obj的隐式转换路径——explicit修饰的构造函数/转换运算符无法参与隐式转换序列,因此编译器找不到合法的转换路径,从而禁止了这次跨类型构造。
关键规则回顾
C++标准规定:在函数调用的参数匹配中,隐式转换序列最多包含一次用户定义转换(自定义构造函数或转换运算符),其余必须是标准内置转换。你的场景中,const_Obj→Obj是唯一的用户定义转换,完全符合规则,因此编译器允许这次构造。
内容的提问来源于stack exchange,提问作者Saitama10000
相关产品推荐
相关产品推荐

