让【道友老李】来帮你解答,本回答参考通义千问大模型编写,并整理提供,如果还有疑问可以点击头像关注私信或评论。
如果答案让您满意,请采纳、关注,非常感谢!
你提供的代码尝试通过遍历结构体的内存来获取成员变量的名字和值,但这种方法存在一些问题。首先,`varName`宏只是将传入的内容转换为字符串,并不是真正的变量名;其次,这种方法假设所有成员变量都是同一种类型,这在实际应用中可能并不成立。
为了正确地遍历结构体或类的所有成员并获取它们的名字和值,我们可以使用C++17引入的std::apply和std::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;
}
代码解释
-
结构体定义:
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;
}
输出
Name: i, Value: 1
Name: i, Value: 2
Name: i, Value: 3
这个方法通过std::tie将结构体成员打包成一个元组,然后使用std::index_sequence和模板递归技术来遍历这些成员。注意,typeid返回的是类型信息,而不是变量名。如果你需要具体的变量名,可以考虑使用编译期反射库如magic_get或Boost.Hana。