类模板构造函数实参的模板类型自动推导问题求助
类模板构造函数的类型推导问题解决方法
你碰到的这个问题其实是C类模板的常见限制——默认情况下类模板没法像函数模板那样自动推导模板参数,不过从C17开始有专门特性解决这个问题,更早版本也有替代方案,我给你详细说说:
方法一:C++17+ 类模板推导指引(推荐)
C++17引入了类模板推导指引,可以明确告诉编译器如何从构造函数参数推导类模板参数。给你的C类加一个推导指引就行:
#include <type_traits> // 使用std::decay_t时需要包含这个头文件 template<typename F> class C { public: C(F&& f) : m_f{f} {} private: F m_f; }; // 类模板推导指引:告诉编译器从构造函数参数推导F template<typename F> C(F&&) -> C<std::decay_t<F>>; // 这里用std::decay_t是为了避免推导成引用类型,确保m_f存储对象副本 // 如果确实需要存储引用,可以去掉std::decay_t,直接写C<F> class D { public: static int s() { return 0; } private: // 现在编译器会自动推导F为decltype(&s),不用手动写模板参数了! C c {&s}; };
为什么加std::decay_t?因为如果传递的是左值(比如命名的函数对象),F&&会被推导成左值引用类型,这时候m_f会是引用,可能导致悬空引用问题。std::decay_t会去掉引用、cv限定符等,让m_f存储对象副本,更安全。
方法二:C++17之前的替代方案——辅助工厂函数
如果你的项目还在用C++17之前的标准,没法用推导指引,可以写一个类似make_shared的辅助函数,借助函数模板的自动推导特性来实现:
template<typename F> class C { public: C(F&& f) : m_f{f} {} private: F m_f; }; // 辅助工厂函数,自动推导F的类型 template<typename F> C<F> make_C(F&& f) { return C<F>(std::forward<F>(f)); } class D { public: static int s() { return 0; } private: // 用decltype推导变量类型,再用make_C构造实例 decltype(make_C(&s)) c = make_C(&s); };
这个方法的核心是利用函数模板的自动推导特性,先通过make_C推导F,再用decltype获取C<F>的类型作为变量c的类型。
这样两种方法都能解决你需要手动指定模板参数的问题,根据你的C++版本选择就行~
内容的提问来源于stack exchange,提问作者Danra
相关产品推荐
相关产品推荐

