C++模板实现is_in函数判断数组含字符串时匹配报错求解
报错原因
- 第二个重载模板参数推导冲突:
is_in的initializer_list重载要求Element类型同时匹配第一个参数和初始化列表内元素的类型。你失败的调用中第一个参数是std::string类型,而{"a", "b", "c"}推导出来的是std::initializer_list<const char*>,两者推导得到的Element类型不一致,触发模板参数推导失败,该重载不会被纳入候选。 - 第一个重载无法推导容器类型:括号初始化列表属于模板非推导上下文,无法自动匹配第一个重载的
Container模板参数,因此第一个重载也无法匹配。
解决方案
最简单的修改方式是调整initializer_list重载的模板参数,将元素类型和待匹配值的类型分开,允许两者可比较即可,同时将待匹配值改为常量引用避免不必要拷贝:
#include <algorithm> #include <initializer_list> template<typename Element, typename Container> bool is_in(const Element& e, const Container& c) { return std::find(std::begin(c), std::end(c), e) != std::end(c); } // 修改后的initializer_list重载,拆分两个参数的类型推导 template<typename Element, typename T> bool is_in(const Element& e, std::initializer_list<T> l) { return is_in<Element, std::initializer_list<T>>(e, l); }
修改后所有测试用例都可以正常编译运行,你也不需要修改原有调用方式。
如果希望严格要求初始化列表的元素类型和待匹配值类型一致,可以使用非推导上下文屏蔽初始化列表侧的类型推导,示例如下(C++20及以上可用):
#include <type_traits> template<typename Element> bool is_in(const Element& e, std::initializer_list<std::type_identity_t<Element>> l) { return is_in<Element, std::initializer_list<Element>>(e, l); }
这种方案下如果初始化列表元素类型和待匹配值不匹配,会触发隐式类型转换,或者直接编译报错。
内容的提问来源于stack exchange,提问作者Androvich
相关产品推荐
相关产品推荐

