如何让接受T&参数的遗留C++函数支持传入MyType类型的临时右值
问题原因
转换运算符方案不可行有两个核心原因:
- C++标准明确规定:当转换的源类型和目标类型为相同类型(包含同一类型的引用、cv限定变体)时,用户定义的类型转换函数会被直接忽略,这就是编译器抛出
-Werror=class-conversion错误的根本原因,即使强行关闭该警告,转换函数也永远不会被调用。 old_space::f是模板函数,在模板实参推导阶段,编译器不会考虑任何用户定义的隐式转换,就算定义了其他类型的转换函数,推导T时仍然会优先匹配传入的MyType右值,直接触发「非const左值引用无法绑定到右值」的编译错误,根本不会走到隐式转换的逻辑。
可行方案
方案1:轻量包装工具(推荐)
无需修改MyType的现有实现,仅需新增一个通用工具函数,零运行时开销,完全符合C++标准:
template<typename T> constexpr std::remove_cvref_t<T>& as_lvalue(T&& val) noexcept { return static_cast<std::remove_cvref_t<T>&>(val); }
调用时对右值参数包裹一层即可:
old_space::f(as_lvalue(g(1)));
该方案仅对显式包裹的参数生效,不会影响其他任何类型的调用逻辑,也不需要修改原有函数定义。
方案2:继承+转换(支持直接调用语法)
如果必须实现old_space::f(g(1))的直接调用语法,且f内部对参数的操作可以兼容基类接口,可通过继承绕开同类型转换的限制:
// 新增基类,定义所有f需要访问的成员/接口 struct MyTypeInterface { // 把MyType中f需要用到的成员函数、虚函数、成员变量都声明在这里 }; struct MyType : public MyTypeInterface { // 原有MyType的全部实现 // 新增右值限定的转换函数,转基类左值引用 operator MyTypeInterface&() && noexcept { return *this; } };
此时调用old_space::f(g(1))时,模板会推导T为MyTypeInterface,可以正常绑定到转换函数返回的左值引用,只要f的逻辑兼容基类接口就可以正常运行。
内容的提问来源于stack exchange,提问作者alfC
相关产品推荐
相关产品推荐

