解析文件时引入类型检查:编译期从字符串取类型索引遇编译错误
问题分析与解决
核心问题
你的代码无法编译的根本原因是:模板参数必须是编译期常量,但get_by_string(s1)的返回值依赖于运行时传入的std::string参数,无法在编译期确定,因此不能作为GetNthTypeT的模板实参。另外代码存在笔误:return INT_T;应改为return INT_ID;。
解决方案
根据字符串是编译期已知还是运行时传入,分两种处理方式:
情况1:字符串是编译期常量(如字面量)
如果传入的字符串是编译期可确定的(比如"int"字面量),改用constexpr std::string_view作为参数,让get_by_string在编译期返回索引:
#include <string_view> static constexpr unsigned INT_ID = 0; static constexpr unsigned DOUBLE_ID = 1; static constexpr unsigned FLOAT_ID = 2; constexpr unsigned get_by_string(std::string_view s1) { if (s1 == "int") return INT_ID; if (s1 == "double") return DOUBLE_ID; if (s1 == "float") return FLOAT_ID; return INT_ID; } // 编译期版本的my_common_with,仅接受编译期字符串 template<std::string_view s1, std::string_view s2> constexpr bool my_common_with() { return std::common_with< GetNthTypeT<MyTypes, get_by_string(s1)>, GetNthTypeT<MyTypes, get_by_string(s2)> >; } // 使用示例 constexpr bool test = my_common_with<"int", "double">(); // 编译期计算
情况2:字符串是运行时传入的
如果字符串只能在运行时确定(比如从文件读取的内容),无法直接用模板元编程处理,需通过运行时分支映射类型并判断std::common_with:
#include <type_traits> #include <string> bool my_common_with(const std::string& s1, const std::string& s2) { // 把字符串映射到类型标签 auto get_type_tag = [](const std::string& s) -> int { if (s == "int") return 0; if (s == "double") return 1; if (s == "float") return 2; return 0; }; auto tag1 = get_type_tag(s1); auto tag2 = get_type_tag(s2); // 运行时分支判断 if (tag1 == 0 && tag2 == 0) return std::common_with<int, int>; if (tag1 == 0 && tag2 == 1) return std::common_with<int, double>; if (tag1 == 0 && tag2 == 2) return std::common_with<int, float>; if (tag1 == 1 && tag2 == 0) return std::common_with<double, int>; if (tag1 == 1 && tag2 == 1) return std::common_with<double, double>; if (tag1 == 1 && tag2 == 2) return std::common_with<double, float>; if (tag1 == 2 && tag2 == 0) return std::common_with<float, int>; if (tag1 == 2 && tag2 == 1) return std::common_with<float, double>; if (tag1 == 2 && tag2 == 2) return std::common_with<float, float>; return false; }
进阶优化:用类型列表自动生成分支
如果类型列表很长,手动写分支繁琐,可通过编译期生成的函数表简化:
#include <array> #include <functional> #include <string> #include <type_traits> // 生成类型对应的判断函数 template<typename T> constexpr auto make_common_with_func() { return [](int tag) -> bool { switch(tag) { case 0: return std::common_with<T, int>; case 1: return std::common_with<T, double>; case 2: return std::common_with<T, float>; default: return false; } }; } // 编译期函数表 constexpr std::array<std::function<bool(int)>, 3> common_with_funcs = { make_common_with_func<int>(), make_common_with_func<double>(), make_common_with_func<float>() }; bool my_common_with(const std::string& s1, const std::string& s2) { auto get_tag = [](const std::string& s) -> unsigned { if (s == "int") return 0; if (s == "double") return 1; if (s == "float") return 2; return 0; }; auto tag1 = get_tag(s1); auto tag2 = get_tag(s2); return common_with_funcs[tag1](tag2); }
内容的提问来源于stack exchange,提问作者milla
相关产品推荐
相关产品推荐

