使用new表达式时类模板实参推导失败问题咨询
问题原因与解决方案
这其实是GCC 7.x版本对C++17类模板参数推导(CTAD)的实现缺陷,不是你的代码不符合标准——C++17标准确实允许在new表达式中对多参数类模板进行自动推导,你写的代码本身是完全合法的。
具体细节
你遇到的差异(new Foo(p)正常但new Bar(p,p)报错),是因为GCC 7.2对new表达式的CTAD支持不完整:它正确处理了单参数类模板的推导,但遗漏了多参数类模板的情况。这个问题是编译器的bug,在GCC 8及以后的版本中已经被修复了。
解决方案
你有两个可行的解决办法:
- 升级编译器:把GCC升级到8.0或更高版本,你的代码就能直接编译通过,不需要任何修改。
- 兼容现有版本的临时方案:
- 显式指定模板参数(虽然这是你不想做的,但可以作为应急手段):
auto heapBar = new Bar<double, double>(p, p); - 写一个辅助工厂函数来包装
new操作,利用函数模板的参数推导间接实现类模板推导:#include <utility> // 用于std::forward template <typename... Args> auto make_bar(Args&&... args) { return new Bar(std::forward<Args>(args)...); } // 调用方式 auto heapBar = make_bar(p, p);
- 显式指定模板参数(虽然这是你不想做的,但可以作为应急手段):
验证标准合规性
根据C++17标准,new表达式中的类模板参数推导规则和栈上对象的推导是一致的——编译器应该根据构造函数的参数推导模板实参。所以你的代码逻辑完全正确,问题出在旧版本GCC的部分实现缺失上。
内容的提问来源于stack exchange,提问作者Ze2j
相关产品推荐
相关产品推荐

