模板模板函数CreateClassA无法自动推导模板参数的原因咨询
嘿,这个问题其实是C++模板参数推导规则里的一个典型场景,咱们一步步拆解来看:
为什么第一个CreateClassA无法推导模板参数?
先看你第一个版本的函数:
template<typename T, template<typename, typename> class Container, typename alloc = std::allocator<T>> std::shared_ptr<ClassA<T, Container, alloc>> CreateClassA(size_t size, double dist) { return std::make_shared<ClassA<T, Container, alloc>>(size, dist); };
当你这样调用时:
size_t size = 5; std::shared_ptr<ClassA<ObjectB, std::vector>> classA2 = CreateClassA(size, 4.5);
C++的模板参数推导有个核心规则:只能基于函数的输入实参来推导,返回值完全不参与推导。这里你的输入参数只有size(size_t类型)和dist(double类型),这俩和模板参数T、Container、alloc半毛钱关系都没有——编译器根本没法从这两个值里猜出你要的是ObjectB和std::vector。虽然你把要赋值的变量类型写得明明白白,但编译器不会逆向从变量类型去推导函数的模板参数,所以自然会报错说无法推导类型。
为什么传入ClassA参数就能推导?
再看第二个版本的函数:
template<typename T, template<typename, typename> class Container, typename alloc = std::allocator<T>> std::shared_ptr<ClassA<T, Container, alloc>> CreateClassA(ClassA<T,Container, alloc> classA, size_t size, double dist) { return std::make_shared<ClassA<T, Container, alloc>>(size, dist); };
这次你调用时传入了ClassA<ObjectB, std::vector>类型的对象classA,这个实参的类型里直接打包了所有需要的模板信息:T=ObjectB、Container=std::vector,还有默认的alloc=std::allocator<ObjectB>。编译器一眼就能从这个输入参数里提取出所有模板参数,自然就能顺利推导了。
更优雅的解决办法(不用传无用的ClassA对象)
其实你完全没必要传一个只是用来凑类型的ClassA对象,有几种更清爽的方式:
- 显式指定模板参数:调用时直接告诉编译器你要的模板参数,跳过推导步骤:
std::shared_ptr<ClassA<ObjectB, std::vector>> classA2 = CreateClassA<ObjectB, std::vector>(size, 4.5); - 简化模板参数列表:直接把
ClassA的完整类型作为模板参数,避免拆分成多个参数:template<typename ClassAType> std::shared_ptr<ClassAType> CreateClassA(size_t size, double dist) { // 可以加个静态断言确保ClassAType是ClassA的实例 static_assert(std::is_base_of_v<ClassA<typename ClassAType::value_type, typename ClassAType::container_type>, ClassAType>, "ClassAType must be an instance of ClassA"); return std::make_shared<ClassAType>(size, dist); }; // 调用时直接指定完整类型 auto classA2 = CreateClassA<ClassA<ObjectB, std::vector>>(size, 4.5);
内容的提问来源于stack exchange,提问作者EliSquared
相关产品推荐
相关产品推荐

