C++可变参数模板练习add_and_cat函数部分场景编译报错求解
问题根源
编译错误的核心原因有两个:
- 字符串字面量类型匹配失败:代码中传入的
"A"这类字符串字面量的原生类型是const char*,而非std::string。模板参数推导阶段不会执行隐式类型转换,因此你定义的接收std::string类型的重载,无法匹配const char*类型的入参。 - 重载覆盖场景不全:你仅提供了第二个入参为
int/std::string的可变参数重载,没有覆盖const char*场景。当递归展开参数时,只要剩余参数的第一个是字符串字面量,就找不到对应的匹配函数,直接抛出编译错误。
你测试用例里部分场景能运行的原因是:当递归到仅剩2个入参时,会匹配到普通函数版本的add_and_cat,普通函数调用阶段允许const char*隐式转换为std::string,所以不会报错。只要剩余参数大于2个且首个是const char*,就会触发匹配失败。
解决方案
方案1:补充const char*类型重载(兼容C++11及以上版本)
直接新增const char*对应的基础版本和可变参数版本重载即可,不需要修改原有逻辑:
// 新增const char*基础处理版本 void add_and_cat(std::pair<int, std::string>& store, const char* s) { store.second += s; } // 新增const char*可变参数版本 template<typename ...Ts> void add_and_cat(std::pair<int, std::string>& store, const char* s, Ts... rest) { store.second += s; add_and_cat(store, rest...); }
添加后所有测试用例都可正常编译运行。
方案2:用C++17 if constexpr 简化实现(更简洁,推荐)
如果使用C++17及以上标准,可以直接写通用可变参数模板,不需要拆分多个类型的重载,代码更易维护:
#include <type_traits> // 递归终止条件:无剩余参数时直接返回 void add_and_cat(std::pair<int, std::string>& store) {} template<typename T, typename ...Ts> void add_and_cat(std::pair<int, std::string>& store, T val, Ts... rest) { if constexpr (std::is_same_v<T, int>) { store.first -= val; } // 自动兼容std::string、const char*等所有可转为string的类型 else if constexpr (std::is_convertible_v<T, std::string>) { store.second += val; } add_and_cat(store, rest...); }
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

