Skip to content

Commit ed251a3

Browse files
committed
fincpp14
1 parent 2c5385b commit ed251a3

File tree

3 files changed

+68
-38
lines changed

3 files changed

+68
-38
lines changed

slides/reflect/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.12)
22

3-
set(CMAKE_CXX_STANDARD 20)
3+
set(CMAKE_CXX_STANDARD 14)
44

55
project(main)
66

slides/reflect/main2.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <memory>
44
#include <sstream>
55
#include <json/json.h>
6-
// #include <pybind11/pybind11.h>
76
#include "reflect.hpp"
87

98

@@ -38,7 +37,7 @@ struct Student {
3837
};
3938

4039

41-
std::string toString(Json::Value root) {
40+
std::string jsonToStr(Json::Value root) {
4241
Json::StreamWriterBuilder builder;
4342
builder["indentation"] = "";
4443
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
@@ -47,48 +46,41 @@ std::string toString(Json::Value root) {
4746
return os.str();
4847
}
4948

50-
Json::Value fromString(std::string const &json) {
49+
Json::Value strToJson(std::string const &json) {
5150
Json::Value root;
5251
Json::Reader reader;
5352
reader.parse(json, root);
5453
return root;
5554
}
5655

57-
template <class T> requires (!reflect_trait<T>::has_member())
58-
Json::Value serialize(T const &object) {
56+
template <class T, std::enable_if_t<!reflect::has_member<T>(), int> = 0>
57+
Json::Value objToJson(T const &object) {
5958
return object;
6059
}
6160

62-
template <class T> requires (reflect_trait<T>::has_member())
63-
Json::Value serialize(T const &object) {
61+
template <class T, std::enable_if_t<reflect::has_member<T>(), int> = 0>
62+
Json::Value objToJson(T const &object) {
6463
Json::Value root;
65-
foreach_member(object, [&](const char *key, auto &value) {
66-
root[key] = serialize(value);
64+
reflect::foreach_member(object, [&](const char *key, auto &value) {
65+
root[key] = objToJson(value);
6766
});
6867
return root;
6968
}
7069

71-
template <class T> requires (!reflect_trait<T>::has_member())
72-
T deserialize(Json::Value const &root) {
70+
template <class T, std::enable_if_t<!reflect::has_member<T>(), int> = 0>
71+
T jsonToObj(Json::Value const &root) {
7372
return root.as<T>();
7473
}
7574

76-
template <class T> requires (reflect_trait<T>::has_member())
77-
T deserialize(Json::Value const &root) {
75+
template <class T, std::enable_if_t<reflect::has_member<T>(), int> = 0>
76+
T jsonToObj(Json::Value const &root) {
7877
T object;
79-
foreach_member(object, [&](const char *key, auto &value) {
80-
value = deserialize<std::decay_t<decltype(value)>>(root[key]);
78+
reflect::foreach_member(object, [&](const char *key, auto &value) {
79+
value = jsonToObj<std::decay_t<decltype(value)>>(root[key]);
8180
});
8281
return object;
8382
}
8483

85-
// PYBIND11_MODULE(pyreflect, m) {
86-
// pybind11::class_<Address> b(m, "Address");
87-
// reflect_trait<Address>::foreach_member_ptr([&] (const char *name, auto member) {
88-
// b.def(name, member);
89-
// });
90-
// }
91-
9284
int main() {
9385
Student stu = {
9486
.name = "Peng",
@@ -99,13 +91,21 @@ int main() {
9991
.city = "Shanghai",
10092
}
10193
};
102-
std::string bin = toString(serialize(stu));
94+
std::string bin = jsonToStr(objToJson(stu));
10395
std::cout << bin << '\n';
104-
auto stuDes = deserialize<Student>(fromString(bin));
96+
auto stuDes = jsonToObj<Student>(strToJson(bin));
10597
std::cout << stuDes.name << '\n';
10698
std::cout << stuDes.age << '\n';
10799
std::cout << stuDes.addr.country << '\n';
108100
std::cout << stuDes.addr.province << '\n';
109101
std::cout << stuDes.addr.city << '\n';
110102
return 0;
111103
}
104+
105+
// #include <pybind11/pybind11.h>
106+
// PYBIND11_MODULE(pyreflect, m) {
107+
// pybind11::class_<Address> b(m, "Address");
108+
// foreach_member_ptr<Address>([&] (const char *name, auto member) {
109+
// b.def(name, member);
110+
// });
111+
// }

slides/reflect/reflect.hpp

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#pragma once
22

33
#include <type_traits>
4+
#include <utility>
45

5-
// easy-to-use static reflection with C++17 and macros
6+
namespace reflect {
7+
8+
// easy-to-use static reflection with C++14 and macros
69

710
// BEGIN GENERATED BY foreachgen.py
811
#define REFLECT__PP_FOREACH_1(f, _1) f(_1)
@@ -47,12 +50,20 @@
4750
#define REFLECT__PP_CONCAT(x, y) REFLECT__PP_CONCAT_2(x, y)
4851
#define REFLECT__PP_FOREACH(f, ...) REFLECT__PP_EXPAND(REFLECT__PP_CONCAT(REFLECT__PP_FOREACH_, REFLECT__PP_NARGS(__VA_ARGS__))(f, __VA_ARGS__))
4952

53+
template <class T>
54+
inline constexpr auto _has_member_test(int) -> decltype(T::template foreach_member_ptr<T>(nullptr), true) {
55+
return true;
56+
}
57+
58+
template <class T>
59+
inline constexpr bool _has_member_test(...) {
60+
return false;
61+
}
62+
5063
template <class T>
5164
struct reflect_trait {
5265
static constexpr bool has_member() {
53-
return requires {
54-
T::template foreach_member_ptr<T>([] (const char *, auto &&) {});
55-
};
66+
return ::reflect::_has_member_test<T>(0);
5667
}
5768

5869
template <class Func>
@@ -66,17 +77,18 @@ struct reflect_trait {
6677

6778
#define REFLECT_TYPE(Type, ...) \
6879
template <> \
69-
struct reflect_trait<Type> { \
80+
struct ::reflect::reflect_trait<Type> { \
7081
using This = Type; \
7182
static constexpr bool has_member() { return true; }; \
7283
template <class Func> \
7384
static constexpr void foreach_member_ptr(Func &&func) { \
7485
REFLECT__PP_FOREACH(REFLECT__TYPE_PER_MEMBER_PTR, __VA_ARGS__) \
7586
} \
87+
};
7688

7789
#define REFLECT_TYPE_TEMPLATED(Type, ...) \
7890
template <__VA_ARGS__> \
79-
struct reflect_trait<REFLECT__PP_EXPAND(REFLECT__PP_EXPAND Type)> { \
91+
struct ::reflect::reflect_trait<REFLECT__PP_EXPAND(REFLECT__PP_EXPAND Type)> { \
8092
using This = REFLECT__PP_EXPAND(REFLECT__PP_EXPAND Type); \
8193
static constexpr bool has_member() { return true; }; \
8294
template <class Func> \
@@ -192,15 +204,33 @@ struct get_member_type<T (*)(Ts...) noexcept> {
192204
#endif
193205

194206
template <class T, class Func>
195-
void foreach_member(T &&object, Func &&func) {
196-
reflect_trait<std::decay_t<T>>::foreach_member_ptr([&] (const char *name, auto member) {
197-
if constexpr (get_member_type<decltype(member)>::value == member_type::member_variable) {
198-
func(name, object.*member);
199-
}
200-
});
207+
struct _foreach_visitor {
208+
T &&object;
209+
Func &&func;
210+
211+
template <class U>
212+
constexpr std::enable_if_t<get_member_type<U>::value == member_type::member_variable>
213+
operator()(const char *name, U member) const {
214+
func(name, object.*member);
215+
}
216+
217+
constexpr void operator()(...) const {}
218+
};
219+
220+
template <class T, class Func>
221+
constexpr void foreach_member(T &&object, Func &&func) {
222+
_foreach_visitor<T, Func> visitor{std::forward<T>(object), std::forward<Func>(func)};
223+
reflect_trait<std::decay_t<T>>::foreach_member_ptr(visitor);
201224
}
202225

203226
template <class T, class Func>
204-
void foreach_member_ptr(Func &&func) {
227+
constexpr void foreach_member_ptr(Func &&func) {
205228
reflect_trait<std::decay_t<T>>::foreach_member_ptr(func);
206229
}
230+
231+
template <class T>
232+
constexpr bool has_member() {
233+
return reflect_trait<std::decay_t<T>>::has_member();
234+
}
235+
236+
}

0 commit comments

Comments
 (0)