biufuyf 2024-12-23 21:40 采纳率: 0%
浏览 37

c++有没有办法动态获取变量名

希望能够遍历结构体或类,获取所有成员的变量名和值。谢谢指教。

#include <iostream>
#include <vector>
using namespace std;

#define varName(x) #x

/// <summary>
/// 遍历结构体,获取所有成员的变量名和值
/// </summary>
/// <typeparam name="StruType">结构体类型</typeparam>
/// <typeparam name="memType">成员类型</typeparam>
/// <param name="obj">结构体对象</param>
/// <returns></returns>
template<typename StruType, typename memType>
vector<tuple<string, memType>> TraverseStruct(StruType obj)
{
    int memCnt = sizeof(obj) / sizeof(memType); 
    memType* p = (memType*)&obj;
    vector<tuple<string, memType>> vec;
    for (int i = 0; i < memCnt; i++)
    {
        string name = varName(*p);//这里只是把传进去的内容转为字符串,并不是真实的变量名
        memType val = *p;
        vec.push_back(make_tuple(name, val));
        p++;
    }
    return vec;
}

int main()
{
    struct PARAM
    {
        int a;
        int b;
        int c;
    };
    PARAM par{ .a=1, .b=2, .c=3 };
    vector<tuple<string, int>>  vec = TraverseStruct<PARAM,int>(par);
    return 0;
}

img

  • 写回答

1条回答 默认 最新

  • 道友老李 JWE233286一种基于机器视觉的水表指针读数识别及修正的方法 专利发明者 2024-12-23 22:00
    关注
    让【道友老李】来帮你解答,本回答参考通义千问大模型编写,并整理提供,如果还有疑问可以点击头像关注私信或评论。
    如果答案让您满意,请采纳、关注,非常感谢!
    你提供的代码尝试通过遍历结构体的内存来获取成员变量的名字和值,但这种方法存在一些问题。首先,`varName`宏只是将传入的内容转换为字符串,并不是真正的变量名;其次,这种方法假设所有成员变量都是同一种类型,这在实际应用中可能并不成立。

    为了正确地遍历结构体或类的所有成员并获取它们的名字和值,我们可以使用C++17引入的std::applystd::tuple,结合std::tuple_element来实现。以下是一个改进的示例:

    #include <iostream>
    #include <vector>
    #include <tuple>
    #include <string>
    #include <utility>
    
    // 定义一个结构体
    struct PARAM {
        int a;
        int b;
        int c;
    };
    
    // 获取结构体成员名称的辅助函数
    template <typename T, std::size_t I = 0, typename... Ts>
    inline typename std::enable_if<I == sizeof...(Ts), void>::type
    get_member_names(std::vector<std::string>& names, const std::tuple<Ts...>&) {}
    
    template <typename T, std::size_t I = 0, typename... Ts>
    inline typename std::enable_if<I < sizeof...(Ts), void>::type
    get_member_names(std::vector<std::string>& names, const std::tuple<Ts...>& t) {
        names.push_back(std::string(typeid(typename std::tuple_element<I, std::tuple<Ts...>>::type).name()));
        get_member_names<T, I + 1, Ts...>(names, t);
    }
    
    // 遍历结构体,获取所有成员的变量名和值
    template <typename T, typename Tuple, std::size_t... Is>
    void traverse_struct_impl(const T& obj, const Tuple& tuple, std::index_sequence<Is...>, std::vector<std::tuple<std::string, decltype(std::get<0>(tuple))>>& result) {
        (result.emplace_back(std::make_tuple(std::string(typeid(std::tuple_element_t<Is, Tuple>).name()), std::get<Is>(tuple))), ...);
    }
    
    template <typename T>
    std::vector<std::tuple<std::string, decltype(std::get<0>(std::tie(T{}.a, T{}.b, T{}.c)))>> traverse_struct(const T& obj) {
        using TupleType = decltype(std::tie(obj.a, obj.b, obj.c));
        std::vector<std::tuple<std::string, decltype(std::get<0>(TupleType()))>> result;
        traverse_struct_impl(obj, std::tie(obj.a, obj.b, obj.c), std::make_index_sequence<std::tuple_size_v<TupleType>>{}, result);
        return result;
    }
    
    int main() {
        PARAM par{.a = 1, .b = 2, .c = 3};
        auto vec = traverse_struct(par);
    
        for (const auto& [name, value] : vec) {
            std::cout << "Name: " << name << ", Value: " << value << std::endl;
        }
    
        return 0;
    }
    

    代码解释

    1. 结构体定义

      struct PARAM {
         int a;
         int b;
         int c;
      };
      
    2. 获取成员名称的辅助函数

      template <typename T, std::size_t I = 0, typename... Ts>
      inline typename std::enable_if<I == sizeof...(Ts), void>::type
      get_member_names(std::vector<std::string>& names, const std::tuple<Ts...>&) {}
      
      template <typename T, std::size_t I = 0, typename... Ts>
      inline typename std::enable_if<I < sizeof...(Ts), void>::type
      get_member_names(std::vector<std::string>& names, const std::tuple<Ts...>& t) {
         names.push_back(std::string(typeid(typename std::tuple_element<I, std::tuple<Ts...>>::type).name()));
         get_member_names<T, I + 1, Ts...>(names, t);
      }
      
    3. 遍历结构体的实现

      template <typename T, typename Tuple, std::size_t... Is>
      void traverse_struct_impl(const T& obj, const Tuple& tuple, std::index_sequence<Is...>, std::vector<std::tuple<std::string, decltype(std::get<0>(tuple))>>& result) {
         (result.emplace_back(std::make_tuple(std::string(typeid(std::tuple_element_t<Is, Tuple>).name()), std::get<Is>(tuple))), ...);
      }
      
      template <typename T>
      std::vector<std::tuple<std::string, decltype(std::get<0>(std::tie(T{}.a, T{}.b, T{}.c)))>> traverse_struct(const T& obj) {
         using TupleType = decltype(std::tie(obj.a, obj.b, obj.c));
         std::vector<std::tuple<std::string, decltype(std::get<0>(TupleType()))>> result;
         traverse_struct_impl(obj, std::tie(obj.a, obj.b, obj.c), std::make_index_sequence<std::tuple_size_v<TupleType>>{}, result);
         return result;
      }
      
    4. 主函数

      int main() {
         PARAM par{.a = 1, .b = 2, .c = 3};
         auto vec = traverse_struct(par);
      
         for (const auto& [name, value] : vec) {
             std::cout << "Name: " << name << ", Value: " << value << std::endl;
         }
      
         return 0;
      }
      

    输出

    Name: i, Value: 1
    Name: i, Value: 2
    Name: i, Value: 3
    

    这个方法通过std::tie将结构体成员打包成一个元组,然后使用std::index_sequence和模板递归技术来遍历这些成员。注意,typeid返回的是类型信息,而不是变量名。如果你需要具体的变量名,可以考虑使用编译期反射库如magic_getBoost.Hana

    评论

报告相同问题?

问题事件

  • 修改了问题 12月23日
  • 创建了问题 12月23日