C++模板编译错误:无法将const TImpl转为TImpl&&,如何避免重复实现私有方法?
问题描述
我定义了以下C++模板类:
template <class TImpl> class PrinterImpl { public: void PrintImpl(const TImpl& t) { std::cout << "&" << t << "\n"; PrintImplPrivate(t); } void PrintImpl(TImpl&& t) { std::cout << "&&" << std::forward<TImpl>(t) << "\n"; PrintImplPrivate(std::forward<TImpl>(t)); } private: void PrintImplPrivate(TImpl&& t) { std::cout << "private print implementation" << t << "\n"; } }; template <class T> class Printer { public: void Print(const T& t) { m_printerImpl.PrintImpl(t); } void Print(T&& t) { m_printerImpl.PrintImpl(std::forward<T>(t)); } private: PrinterImpl<T> m_printerImpl; };
执行以下代码时:
int main() { int x = 0; Printer<int> p; p.Print(x); }
出现编译错误:
error C2664: 'void PrinterImpl
::PrintImplPrivate(TImpl &&)': cannot convert argument 1 from 'const TImpl' to 'TImpl &&'
请问是否有办法避免为右值引用和const引用重复实现PrinterImpl类中的私有方法?
解决方案
当然可以,无需重复实现私有方法,有两种简洁的解决思路:
方案1:使用转发引用适配所有参数类型
将私有方法改为模板函数,利用转发引用自动适配左值、右值以及带const修饰的参数,保留参数的原始值类别(适合需要移动语义的场景):
template <class TImpl> class PrinterImpl { public: void PrintImpl(const TImpl& t) { std::cout << "&" << t << "\n"; PrintImplPrivate(t); } void PrintImpl(TImpl&& t) { std::cout << "&&" << std::forward<TImpl>(t) << "\n"; PrintImplPrivate(std::forward<TImpl>(t)); } private: // 模板转发引用方法,自动匹配所有参数类型和值类别 template <typename U> void PrintImplPrivate(U&& t) { std::cout << "private print implementation" << t << "\n"; } };
方案2:使用const引用统一接收参数
如果私有方法不需要区分参数的值类别(不需要移动操作),直接将私有方法的参数设为const TImpl&,因为左值、右值都可以绑定到const引用,实现更简单:
template <class TImpl> class PrinterImpl { public: void PrintImpl(const TImpl& t) { std::cout << "&" << t << "\n"; PrintImplPrivate(t); } void PrintImpl(TImpl&& t) { std::cout << "&&" << std::forward<TImpl>(t) << "\n"; PrintImplPrivate(t); // 右值可直接绑定到const引用 } private: void PrintImplPrivate(const TImpl& t) { std::cout << "private print implementation" << t << "\n"; } };
两种方案都能解决编译错误,且无需重复编写私有方法的逻辑,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者Dom
相关产品推荐
相关产品推荐

