C++模板函数中使用typeid引发编译错误:const char*转int无效
问题现象
编译变参模板实现的求和代码时,触发编译错误:将const char转换为int为无效操作*。
报错时使用的代码如下:
#include <iostream> #include <typeinfo> using namespace std; int sums() { return 0; } template <typename Type, typename... T> int sums(const Type s, const T... args) { int res = 0; if (typeid(s) == typeid(int)) { res += s; } else { cout << "not int" << s << endl; } res += sums(args...); return res; } int main() { cout << sums(1,"sir", 4) << endl; return 0; }
错误根因
这个错误是对C++分支检查逻辑理解偏差导致的:
typeid是运行时类型识别(RTTI)工具,对应的if判断是运行时才会执行的分支逻辑- C++编译阶段会检查所有分支代码的类型合法性,不会因为某个分支运行时永远不会走到,就跳过该分支的类型校验
- 当模板实例化到
s为const char*类型(也就是传入字符串字面量"sir")时,编译器依然会检查if块内的res += s语句,此时右侧操作数是const char*类型,无法隐式转换为int和左侧int类型的res做加法,直接触发编译错误。
修复方案
根据使用的C++标准版本,选对应方案即可:
C++17及以上版本(推荐)
使用C++17引入的if constexpr编译期分支,编译器会在编译阶段判断条件,直接丢弃不满足条件的分支代码,不会对丢弃分支做类型检查,从根源避免非法类型转换问题。
修复后完整代码:
#include <iostream> #include <type_traits> // 使用is_same_v需要引入该头文件 using namespace std; int sums() { return 0; } template <typename Type, typename... T> int sums(const Type s, const T... args) { int res = 0; // 编译期判断类型,非int分支直接丢弃,不会生成res += const char*的非法代码 if constexpr (is_same_v<Type, int>) { res += s; } else { cout << "not int: " << s << endl; } res += sums(args...); return res; } int main() { cout << sums(1,"sir", 4) << endl; return 0; }
运行输出:
not int: sir 5
C11/C14版本(无if constexpr支持)
通过函数重载+编译期决议实现类型分流,针对int类型和非int类型分别写处理逻辑,避免非法类型操作:
#include <iostream> using namespace std; int sums() { return 0; } // 非int类型参数的处理逻辑 template <typename T> int param_process(const T& s) { cout << "not int: " << s << endl; return 0; } // int类型参数的处理逻辑 int param_process(int s) { return s; } template <typename Type, typename... T> int sums(const Type s, const T... args) { int res = param_process(s); res += sums(args...); return res; } int main() { cout << sums(1,"sir", 4) << endl; return 0; }
运行结果和C++17版本完全一致。
内容的提问来源于stack exchange,提问作者sirun wang
相关产品推荐
相关产品推荐

