ORM-Lite 源码分析

24 Nov 2024 | cpp, code

修订历史

  • 2024.11.24 移出私密

https://github.com/BOT-Man-JL/ORM-Lite
https://bot-man-jl.github.io/articles/?post=2018/Cpp-Struct-Field-Reflection

成员指针

class CA {
public:
  int m_i0;
private:
  int m_i1;
};

int CA::* pm = &CA::m_i0;

CA a;
CA* p = &a;
a.*pm = 5;
p->*pm = 6;

C++反射

动态反射

chromium/base::Value

template <typename FieldType>
using ValueConverter =
    std::function<void(FieldType* field, const std::string& name)>;

template <typename StructType>
class FieldConverterBase {
 public:
  virtual ~FieldConverterBase() = default;
  virtual void operator()(StructType* obj) const = 0;
};

template <typename StructType, typename FieldType>
class FieldConverter : public FieldConverterBase<StructType> {
 public:
  FieldConverter(const std::string& name,
                 FieldType StructType::*pointer,
                 ValueConverter<FieldType> converter)
      : field_name_(name),
        field_pointer_(pointer),
        value_converter_(converter) {}

  void operator()(StructType* obj) const override {
    return value_converter_(&(obj->*field_pointer_), field_name_);
  }

 private:
  std::string field_name_;
  FieldType StructType::*field_pointer_;
  ValueConverter<FieldType> value_converter_;
};

template <class StructType>
class StructValueConverter {
 public:
  template <typename FieldType>
  void RegisterField(FieldType StructType::*field_pointer,
                     const std::string& field_name,
                     ValueConverter<FieldType> value_converter) {
    fields_.push_back(std::make_unique<FieldConverter<StructType, FieldType>>(
        field_name, field_pointer, std::move(value_converter)));
  }

  void operator()(StructType* obj) const {
    for (const auto& field_converter : fields_) {
      (*field_converter)(obj);
    }
  }

 private:
  std::vector<std::unique_ptr<FieldConverterBase<StructType>>> fields_;
};

struct SimpleStruct {
  bool bool_;
  int int_;
  double double_;
  std::string string_;
};

int main() {
  auto bool_converter = [](bool* field, const std::string& name) {
    std::cout << std::boolalpha << name << ": " << *field << std::endl;
  };
  auto int_converter = [](int* field, const std::string& name) {
    std::cout << name << ": " << *field << std::endl;
  };
  auto double_converter = [](double* field, const std::string& name) {
    std::cout << std::fixed << name << ": " << *field << std::endl;
  };
  auto string_converter = [](std::string* field, const std::string& name) {
    std::cout << name << ": " << *field << std::endl;
  };

  StructValueConverter<SimpleStruct> converter;
  converter.RegisterField(&SimpleStruct::bool_, "bool",
                          ValueConverter<bool>(bool_converter));
  converter.RegisterField(&SimpleStruct::int_, "int",
                          ValueConverter<int>(int_converter));
  converter.RegisterField(&SimpleStruct::double_, "double",
                          ValueConverter<double>(double_converter));
  converter.RegisterField(&SimpleStruct::string_, "string",
                          ValueConverter<std::string>(string_converter));

  SimpleStruct simple{true, 2, 2.0, "hello dynamic reflection"};
  converter(&simple);
}

关键点如下:

class Base { ... };
class Derive1 : Base {
    void operator(class) { 
        ... 
        fun(class.*pClassMem); 
        ... 
    }
};
class Derive2 : Base { ... };

class Factory {
    void register(pClassMem, fun); // 实例化Derive,push进v
    void operator(class){ for_each(v.begin(), v.end(),  ...); }; // 遍历v
    
    vector<&Base> v;
};

静态反射

namespace detail {

template <typename Fn, typename Tuple, std::size_t... I>
inline constexpr void ForEachTuple(Tuple&& tuple,
                                   Fn&& fn,
                                   std::index_sequence<I...>) {
  using Expander = int[];
  (void)Expander{0, ((void)fn(std::get<I>(std::forward<Tuple>(tuple))), 0)...};
}

template <typename Fn, typename Tuple>
inline constexpr void ForEachTuple(Tuple&& tuple, Fn&& fn) {
  ForEachTuple(
      std::forward<Tuple>(tuple), std::forward<Fn>(fn),
      std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
}

template <typename T>
struct is_field_pointer : std::false_type {};

template <typename C, typename T>
struct is_field_pointer<T C::*> : std::true_type {};

template <typename T>
constexpr auto is_field_pointer_v = is_field_pointer<T>::value;

}  // namespace detail

template <typename T>
inline constexpr auto StructSchema() {
  return std::make_tuple();
}

#define DEFINE_STRUCT_SCHEMA(Struct, ...)        \
  template <>                                    \
  inline constexpr auto StructSchema<Struct>() { \
    using _Struct = Struct;                      \
    return std::make_tuple(__VA_ARGS__);         \
  }

#define DEFINE_STRUCT_FIELD(StructField, FieldName) \
  std::make_tuple(&_Struct::StructField, FieldName)

template <typename T, typename Fn>
inline constexpr void ForEachField(T&& value, Fn&& fn) {
  constexpr auto struct_schema = StructSchema<std::decay_t<T>>();
  static_assert(std::tuple_size<decltype(struct_schema)>::value != 0,
                "StructSchema<T>() for type T should be specialized to return "
                "FieldSchema tuples, like ((&T::field, field_name), ...)");

  detail::ForEachTuple(struct_schema, [&value, &fn](auto&& field_schema) {
    using FieldSchema = std::decay_t<decltype(field_schema)>;
    static_assert(
        std::tuple_size<FieldSchema>::value >= 2 &&
            detail::is_field_pointer_v<std::tuple_element_t<0, FieldSchema>>,
        "FieldSchema tuple should be (&T::field, field_name)");

    fn(value.*(std::get<0>(std::forward<decltype(field_schema)>(field_schema))),
       std::get<1>(std::forward<decltype(field_schema)>(field_schema)));
  });
}

// 使用方法

struct SimpleStruct {
  bool bool_;
  int int_;
  double double_;
  std::string string_;
};

DEFINE_STRUCT_SCHEMA(SimpleStruct,
                     DEFINE_STRUCT_FIELD(bool_, "bool"),
                     DEFINE_STRUCT_FIELD(int_, "int"),
                     DEFINE_STRUCT_FIELD(double_, "double"),
                     DEFINE_STRUCT_FIELD(string_, "string"));

struct GenericFunctor {
  // ... context data

  template <typename Field, typename Name>
  void operator()(Field&& field, Name&& name) {
    std::cout << std::boolalpha << std::fixed << name << ": " << field
              << std::endl;
  }
};

namespace {

template <class... Fs>
struct overload_set;

template <class F1, class... Fs>
struct overload_set<F1, Fs...> : F1, overload_set<Fs...>::type {
  typedef overload_set type;

  overload_set(F1 head, Fs... tail)
      : F1(head), overload_set<Fs...>::type(tail...) {}

  using F1::operator();
  using overload_set<Fs...>::type::operator();
};

template <class F>
struct overload_set<F> : F {
  typedef F type;
  using F::operator();
};

template <class... Fs>
typename overload_set<Fs...>::type overload(Fs... x) {
  return overload_set<Fs...>(x...);
}

}  // namespace

int main() {
  ForEachField(SimpleStruct{true, 1, 1.0, "hello static reflection"},
               [](auto&& field, auto&& name) {
                 std::cout << std::boolalpha << std::fixed << name << ": "
                           << field << std::endl;
               });

  ForEachField(SimpleStruct{true, 1, 1.0, "hello static reflection"},
               GenericFunctor{/* ... context data */});

  ForEachField(SimpleStruct{true, 1, 1.0, "hello static reflection"},
               overload(
                   [](bool field, const char* name) {
                     std::cout << "b " << std::boolalpha << name << ": "
                               << field << std::endl;
                   },
                   [](int field, const char* name) {
                     std::cout << "i " << name << ": " << field << std::endl;
                   },
                   [](double field, const char* name) {
                     std::cout << "d " << std::fixed << name << ": " << field
                               << std::endl;
                   },
                   [](const std::string& field, const char* name) {
                     std::cout << "s " << name << ": " << field.c_str()
                               << std::endl;
                   }));
  return 0;
}

关键点:

另一个静态反射

https://zhuanlan.zhihu.com/p/112914534


Older · View Archive (39)

MySQL实战45讲