C++20中隐式调用转换函数的表达式类别是否与显式调用一致?
关于C++20中隐式调用转换函数的表达式类别疑问
基于C++20工作草案N4868,在类的复制初始化场景中,隐式调用转换构造函数时,标准明确该调用为prvalue表达式,但使用转换函数进行类类型复制初始化和基础类型初始化的情况,标准描述并不清晰。
相关标准引用
标准引用1:[dcl.init.general]/16.6.3
否则(即剩余的复制初始化情况),枚举可将源类型转换为目标类型或(使用转换函数时)转换为其派生类的用户定义转换(如12.4.2.5所述),并通过重载决议(12.4)选择最佳转换。若无法完成转换或存在歧义,则初始化格式错误。所选函数以初始化表达式作为参数调用;若该函数是构造函数,则此调用是目标类型的cv非限定版本的prvalue,其结果对象由构造函数初始化。此调用用于按照上述规则直接初始化作为复制初始化目标的对象。
标准引用2:[dcl.init.general]/16.7
否则,若源类型是(可能带cv限定的)类类型,则考虑转换函数。枚举适用的转换函数(12.4.2.6),并通过重载决议(12.4)选择最佳转换。**调用所选的用户定义转换,将初始化表达式转换为正在初始化的对象。**若无法完成转换或存在歧义,则初始化格式错误。
代码示例
struct MyClass { int m_int {}; double m_double {}; MyClass() = default; MyClass(double x) { //nothing } operator double() { return m_double; } operator int&() { return m_int; } }; int main() { MyClass object; int& x = object; //隐式调用转换函数是否为类似static_cast<int&>(object)的lvalue表达式? double y = object; //隐式调用转换函数是否为类似static_cast<double>(object)的prvalue表达式? MyClass other_object = 4.0; //隐式调用转换构造函数为类似MyClass(4.0)的prvalue; }
核心问题
隐式调用转换函数的表达式类别(prvalue、xvalue、lvalue等)是否与显式调用一致?
分析结论
- 根据[conv.general]/6,任何隐式转换的结果都具备明确的表达式类别;
- [expr.call]/14规定函数调用的表达式类别由返回类型决定:返回引用类型的函数调用结果为lvalue,返回对象类型的函数调用结果为prvalue;
- 结合上述条款可推测:隐式调用转换函数的表达式类别规则与显式调用完全一致;
- 实际验证(Clang AST分析)及社区讨论结论也支持这一推测:
- 对于返回引用的转换函数(如示例中的
operator int&()),隐式调用的结果是lvalue,与static_cast<int&>(object)的表达式类别一致; - 对于返回非引用类型的转换函数(如示例中的
operator double()),隐式调用的结果是prvalue,与static_cast<double>(object)的表达式类别一致。
- 对于返回引用的转换函数(如示例中的
内容的提问来源于stack exchange,提问作者Manuel
相关产品推荐
相关产品推荐

