C++编译期循环获取变量类型详情
目录
- 一、问题
- 二、解决方案
- 1.定义类型
- 2.定义属性集
- 3. 获取类型索引
- 4. 编译期循环
- 总结
一、问题 假设现在有一些属性以及这些属性对应的数值类型,比如:
"gender" --> char"age" --> int"height" --> float"IQ" ---> int"name" --> std::string"weight" --> double
【C++编译期循环获取变量类型详情】在C++中,如何在编译期依次循环获取这些属性的数值类型,并根据对应的数值类型做出相应的处理(属性可能会增加)
二、解决方案
1.定义类型
首先把所有可能的类型用std::tuple列出:
using Types = std::tuple; templateusing AttributeType = typename std::tuple_element ::type;
这里,通过AttributeType<0>就可以得到float 类型
2.定义属性集
将所有的属性和其类型的对应关系列出,由于需要是编译期获得,必须类似加入constexpr 关键字:
constexpr const char* FLOAT_TYPE = "float"; constexpr const char* INT_TYPE = "int"; constexpr const char* DOUBLE_TYPE = "double"; constexpr const char* STRING_TYPE = "std::string"; constexpr const char* CHAR_TYPE = "float"; constexpr std::array, 6> attribute2type = {{{"gender", CHAR_TYPE},{"age", INT_TYPE},{"height", FLOAT_TYPE},{"IQ", INT_TYPE},{"name", STRING_TYPE},{"weight", DOUBLE_TYPE},}};
3. 获取类型索引
根据2中定义的类型字符串,获取1中需要的类型索引N:
constexpr std::size_t getTypeIndex(const char* name){return strings_equal(name, "float") ? 0:strings_equal(name, "int") ? 1:strings_equal(name, "double") ? 2:strings_equal(name, "std::string") ? 3:strings_equal(name, "char") ? 4:5; // compilation error}
这里,需要一个编译期进行字符串比较的函数:
constexpr bool strings_equal(const char* a, const char* b) {return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1)); }
4. 编译期循环
如何实现编译期的类似for循环呢,显然不能直接用for,模板的特性决定了可以使用编译期递归来进行替代for循环:
templatevoid print(const char* attribute) {std::cout << "attribute = " << attribute << ",type=" < (); }private:template void doPrint() {print(attribute2type).second)>>(std::get (attribute2type).first); doPrint (); }}; template <>template <>void PrintHelper ::doPrint<0>() {print(attribute2type).second)>>(std::get<0>(attribute2type).first); }
将上面所有的代码放到一块,就得到了一个可以在编译期循环获取变量类型的程序:
#include #include#include #include #include using Types = std::tuple ; templateusing AttributeType = typename std::tuple_element ::type; constexpr bool strings_equal(const char* a, const char* b) {return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1)); }constexpr std::size_t getTypeIndex(const char* name){return strings_equal(name, "float") ? 0:strings_equal(name, "int") ? 1:strings_equal(name, "double") ? 2:strings_equal(name, "std::string") ? 3:strings_equal(name, "char") ? 4:5; // compilation error}constexpr const char* FLOAT_TYPE = "float"; constexpr const char* INT_TYPE = "int"; constexpr const char* DOUBLE_TYPE = "double"; constexpr const char* STRING_TYPE = "std::string"; constexpr const char* CHAR_TYPE = "float"; constexpr std::array, 6> attribute2type = {{{"gender", CHAR_TYPE},{"age", INT_TYPE},{"height", FLOAT_TYPE},{"IQ", INT_TYPE},{"name", STRING_TYPE},{"weight", DOUBLE_TYPE},}}; template void print(const char* attribute) {std::cout << "attribute = " << attribute << ",type=" < (); }private:template void doPrint() {print(attribute2type).second)>>(std::get (attribute2type).first); doPrint (); }}; template <>template <>void PrintHelper ::doPrint<0>() {print(attribute2type).second)>>(std::get<0>(attribute2type).first); }int main() {PrintHelper (); return 0; }
上面程序输出:
$ ./attributeWithType
attribute = weight,type=d
attribute = name,type=NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
attribute = IQ,type=i
attribute = height,type=f
attribute = age,type=i
attribute = gender,type=f
总结 本文通过下面几个技术点实现了编译期循环获取变量类型:
- 通过std::tuple定义变量类型集合,
- 通过typename std::tuple_element
::type获取某个变量类型 - 通过编译期递归实现编译期字符串比较
- 通过std::get(attribute2type)获取属性编译期递归实现循环获取变量类型
推荐阅读
- C++模板超详细介绍
- C/C++预处理浅析使用形式
- 投稿|战略见效股价下跌扭转,Paypal熬过最危险时期?
- 大学生科研那些事(一)
- 亲子日记第二十九天,1月3日,星期三,天气,阴
- 投稿|临期折扣店稍纵即逝的夏天
- 新消费|零糖赛道产能日趋饱和华康股份此时募资加码能否把握窗口期?
- 知乎问题之(.NET|知乎问题之:.NET AOT编译后能替代C++吗())
- 死本能-272
- #放晴丘壑#|#放晴丘壑# 如何订机票