C语言编译期如何通过循环获取任意变量类型详细信息?

2026-04-18 15:012阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1423个文字,预计阅读时间需要6分钟。

C语言编译期如何通过循环获取任意变量类型详细信息?

目录

一、问题

二、解决方案

1.定义类型

2.定义属性集

3.获取类型索引

4.编译期循环

总结

一、问题

假设有一个对象,它包含一些属性及其对应的数值类型,如性别和年龄。

二、解决方案

1.定义类型

pythonclass Person: pass

2. 定义属性集pythonclass Person: attributes={ 'gender': str, 'age': int }

3. 获取类型索引pythonclass Person: attributes={ 'gender': str, 'age': int }

@classmethod def get_attribute_type(cls, attribute): return cls.attributes.get(attribute)

4. 编译期循环pythonclass Person: attributes={ 'gender': str, 'age': int }

@classmethod def get_attribute_type(cls, attribute): return cls.attributes.get(attribute)

def __init__(self, **kwargs): for attr, value in kwargs.items(): if attr in self.attributes: setattr(self, attr, value)

总结

目录
  • 一、问题
  • 二、解决方案
    • 1.定义类型
    • 2.定义属性集
    • 3. 获取类型索引
    • 4. 编译期循环
  • 总结

    一、问题

    假设现在有一些属性以及这些属性对应的数值类型,比如:

    "gender" --> char "age" --> int "height" --> float "IQ" ---> int "name" --> std::string "weight" --> double

    在C++中,如何在编译期依次循环获取这些属性的数值类型,并根据对应的数值类型做出相应的处理(属性可能会增加)

    二、解决方案

    1.定义类型

    首先把所有可能的类型用std::tuple列出:

    C语言编译期如何通过循环获取任意变量类型详细信息?

    using Types = std::tuple<float, int, double, std::string, char>; template<std::size_t N> using AttributeType = typename std::tuple_element<N, Types>::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<std::pair<const char*, const char*>, 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循环:

    template <typename T> void print(const char* attribute) { std::cout << "attribute = " << attribute << ",type=" << typeid(T).name() << std::endl; } constexpr size_t LAST_INDEX = attribute2type.size() - 1; template <size_t T=LAST_INDEX> struct PrintHelper { public: PrintHelper() { doPrint<T>(); } private: template <size_t N> void doPrint() { print<AttributeType<getTypeIndex(std::get<N>(attribute2type).second)>>(std::get<N>(attribute2type).first); doPrint<N-1>(); } }; template <> template <> void PrintHelper<LAST_INDEX>::doPrint<0>() { print<AttributeType<getTypeIndex(std::get<0>(attribute2type).second)>>(std::get<0>(attribute2type).first); }

    将上面所有的代码放到一块,就得到了一个可以在编译期循环获取变量类型的程序:

    #include <string> #include <iostream> #include <typeinfo> #include <tuple> #include <array> using Types = std::tuple<float, int, double, std::string, char>; template<std::size_t N> using AttributeType = typename std::tuple_element<N, Types>::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<std::pair<const char*, const char*>, 6> attribute2type = {{ {"gender", CHAR_TYPE}, {"age", INT_TYPE}, {"height", FLOAT_TYPE}, {"IQ", INT_TYPE}, {"name", STRING_TYPE}, {"weight", DOUBLE_TYPE}, }}; template <typename T> void print(const char* attribute) { std::cout << "attribute = " << attribute << ",type=" << typeid(T).name() << std::endl; } constexpr size_t LAST_INDEX = attribute2type.size() - 1; template <size_t T=LAST_INDEX> struct PrintHelper { public: PrintHelper() { doPrint<T>(); } private: template <size_t N> void doPrint() { print<AttributeType<getTypeIndex(std::get<N>(attribute2type).second)>>(std::get<N>(attribute2type).first); doPrint<N-1>(); } }; template <> template <> void PrintHelper<LAST_INDEX>::doPrint<0>() { print<AttributeType<getTypeIndex(std::get<0>(attribute2type).second)>>(std::get<0>(attribute2type).first); } int main() { PrintHelper<LAST_INDEX>(); 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<N, Types>::type获取某个变量类型
    • 通过编译期递归实现编译期字符串比较
    • 通过std::get(attribute2type)获取属性编译期递归实现循环获取变量类型

    到此这篇关于C++编译期循环获取变量类型详情的文章就介绍到这了,更多相关C++循环获取变量类型内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

    本文共计1423个文字,预计阅读时间需要6分钟。

    C语言编译期如何通过循环获取任意变量类型详细信息?

    目录

    一、问题

    二、解决方案

    1.定义类型

    2.定义属性集

    3.获取类型索引

    4.编译期循环

    总结

    一、问题

    假设有一个对象,它包含一些属性及其对应的数值类型,如性别和年龄。

    二、解决方案

    1.定义类型

    pythonclass Person: pass

    2. 定义属性集pythonclass Person: attributes={ 'gender': str, 'age': int }

    3. 获取类型索引pythonclass Person: attributes={ 'gender': str, 'age': int }

    @classmethod def get_attribute_type(cls, attribute): return cls.attributes.get(attribute)

    4. 编译期循环pythonclass Person: attributes={ 'gender': str, 'age': int }

    @classmethod def get_attribute_type(cls, attribute): return cls.attributes.get(attribute)

    def __init__(self, **kwargs): for attr, value in kwargs.items(): if attr in self.attributes: setattr(self, attr, value)

    总结

    目录
    • 一、问题
    • 二、解决方案
      • 1.定义类型
      • 2.定义属性集
      • 3. 获取类型索引
      • 4. 编译期循环
    • 总结

      一、问题

      假设现在有一些属性以及这些属性对应的数值类型,比如:

      "gender" --> char "age" --> int "height" --> float "IQ" ---> int "name" --> std::string "weight" --> double

      在C++中,如何在编译期依次循环获取这些属性的数值类型,并根据对应的数值类型做出相应的处理(属性可能会增加)

      二、解决方案

      1.定义类型

      首先把所有可能的类型用std::tuple列出:

      C语言编译期如何通过循环获取任意变量类型详细信息?

      using Types = std::tuple<float, int, double, std::string, char>; template<std::size_t N> using AttributeType = typename std::tuple_element<N, Types>::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<std::pair<const char*, const char*>, 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循环:

      template <typename T> void print(const char* attribute) { std::cout << "attribute = " << attribute << ",type=" << typeid(T).name() << std::endl; } constexpr size_t LAST_INDEX = attribute2type.size() - 1; template <size_t T=LAST_INDEX> struct PrintHelper { public: PrintHelper() { doPrint<T>(); } private: template <size_t N> void doPrint() { print<AttributeType<getTypeIndex(std::get<N>(attribute2type).second)>>(std::get<N>(attribute2type).first); doPrint<N-1>(); } }; template <> template <> void PrintHelper<LAST_INDEX>::doPrint<0>() { print<AttributeType<getTypeIndex(std::get<0>(attribute2type).second)>>(std::get<0>(attribute2type).first); }

      将上面所有的代码放到一块,就得到了一个可以在编译期循环获取变量类型的程序:

      #include <string> #include <iostream> #include <typeinfo> #include <tuple> #include <array> using Types = std::tuple<float, int, double, std::string, char>; template<std::size_t N> using AttributeType = typename std::tuple_element<N, Types>::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<std::pair<const char*, const char*>, 6> attribute2type = {{ {"gender", CHAR_TYPE}, {"age", INT_TYPE}, {"height", FLOAT_TYPE}, {"IQ", INT_TYPE}, {"name", STRING_TYPE}, {"weight", DOUBLE_TYPE}, }}; template <typename T> void print(const char* attribute) { std::cout << "attribute = " << attribute << ",type=" << typeid(T).name() << std::endl; } constexpr size_t LAST_INDEX = attribute2type.size() - 1; template <size_t T=LAST_INDEX> struct PrintHelper { public: PrintHelper() { doPrint<T>(); } private: template <size_t N> void doPrint() { print<AttributeType<getTypeIndex(std::get<N>(attribute2type).second)>>(std::get<N>(attribute2type).first); doPrint<N-1>(); } }; template <> template <> void PrintHelper<LAST_INDEX>::doPrint<0>() { print<AttributeType<getTypeIndex(std::get<0>(attribute2type).second)>>(std::get<0>(attribute2type).first); } int main() { PrintHelper<LAST_INDEX>(); 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<N, Types>::type获取某个变量类型
      • 通过编译期递归实现编译期字符串比较
      • 通过std::get(attribute2type)获取属性编译期递归实现循环获取变量类型

      到此这篇关于C++编译期循环获取变量类型详情的文章就介绍到这了,更多相关C++循环获取变量类型内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!