Skip to content

Commit

Permalink
[struct_pb][fix and feat]1. fix当成员是std::variant类型时.get_fields_name 会有…
Browse files Browse the repository at this point in the history
…重复字段名bug;2.添加get_field_any接口,具体类型转换延迟到用户端代码 (#698)
  • Loading branch information
171930433 authored Jun 25, 2024
1 parent 6274f8a commit 865be82
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 10 deletions.
40 changes: 35 additions & 5 deletions include/ylt/standalone/iguana/pb_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cstddef>
#include <cstring>
#include <map>
#include <set>
#include <stdexcept>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -76,20 +77,49 @@ struct base_impl : public base {
return info;
}

std::vector<std::string_view> get_fields_name() override {
std::vector<std::string_view> get_fields_name() const override {
static constexpr auto map = iguana::get_members<T>();

std::vector<std::string_view> vec;
for (auto [no, val] : map) {
std::set<std::string_view> sets;

for (auto const& [no, val] : map) {
std::visit(
[&](auto& field) {
vec.push_back(std::string_view(field.field_name.data(),
field.field_name.size()));
[&](auto const& field) {
if (auto it = sets.emplace(field.field_name.data(),
field.field_name.size());
it.second) {
vec.push_back(*it.first);
}
},
val);
}
return vec;
}

std::any get_field_any(std::string_view name) const override {
static constexpr auto map = iguana::get_members<T>();
std::any result;

for (auto [no, field] : map) {
if (result.has_value()) {
break;
}
std::visit(
[&](auto val) {
if (val.field_name == name) {
using value_type = typename decltype(val)::value_type;
auto const offset = member_offset((T*)this, val.member_ptr);
auto ptr = (((char*)this) + offset);
result = {*((value_type*)ptr)};
}
},
field);
}

return result;
}

virtual ~base_impl() {}

size_t cache_size = 0;
Expand Down
4 changes: 3 additions & 1 deletion include/ylt/standalone/iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#ifndef IGUANA_REFLECTION_HPP
#define IGUANA_REFLECTION_HPP
#include <any>
#include <array>
#include <functional>
#include <iomanip>
Expand Down Expand Up @@ -563,7 +564,8 @@ struct field_info {
struct base {
virtual void to_pb(std::string &str) {}
virtual void from_pb(std::string_view str) {}
virtual std::vector<std::string_view> get_fields_name() { return {}; }
virtual std::vector<std::string_view> get_fields_name() const { return {}; }
virtual std::any get_field_any(std::string_view name) const { return {}; }
virtual iguana::detail::field_info get_field_info(std::string_view name) {
return {};
}
Expand Down
23 changes: 19 additions & 4 deletions src/struct_pb/examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ struct nest : struct_pb::base_impl<nest> {
std::string name;
my_struct value;
int var;
std::variant<int, double> mv;
};
REFLECTION(nest, name, value, var);
REFLECTION(nest, name, value, var, mv);

struct person {
int id;
Expand Down Expand Up @@ -52,17 +53,31 @@ int main() {
// dynamic reflection
auto t = struct_pb::create_instance("nest");
auto names = t->get_fields_name();
bool r = (names == std::vector<std::string_view>{"name", "value", "var"});
bool r =
(names == std::vector<std::string_view>{"name", "value", "var", "mv"});
assert(r);

t->set_field_value("mv", std::variant<int, double>{1});
auto mv = t->get_field_value<std::variant<int, double>>("mv");
auto const temp = std::variant<int, double>{1};
assert(mv == temp);

t->set_field_value("name", std::string("tom"));
auto name = t->get_field_value<std::string>("name");
assert(name == "tom");

auto d = dynamic_cast<nest *>(t.get());
auto d = dynamic_cast<nest*>(t.get());
assert(d->name == "tom");

t->set_field_value<std::string>("name", "hello");
auto &field_name = t->get_field_value<std::string>("name");
auto& field_name = t->get_field_value<std::string>("name");
assert(field_name == "hello");

// dynamic any
auto const& any_name = t->get_field_any("name");
assert(std::any_cast<std::string>(any_name) == "hello");

auto const& mvar_any = t->get_field_any("mv");
auto const& mvar = std::any_cast<std::variant<int, double>>(mvar_any);
assert(mvar == temp);
}

0 comments on commit 865be82

Please sign in to comment.