zeusUnnamed repository; edit this file 'description' to name the repository. |
git clone Unknown |
Log | Files | Refs |
dsl_transactions.cpp (2121B)
0 #include <utility>
1 #include <functional>
2 #include <string>
4 template<class Member, class Value>
5 struct update {
6 update(Member member, Value value) : member(member), value(value) {}
8 template<typename Record>
9 bool operator()(Record& record) {
10 if constexpr(std::is_invocable_r<bool, Member, Record, Value>()) {
11 return std::invoke(member, record, value);
12 } else if constexpr (std::is_invocable<Member, Record, Value>()) {
13 std::invoke(member, record, value);
14 return true;
15 } else {
16 std::invoke(member, record) = value;
17 return true;
18 }
19 }
21 Member member;
22 Value value;
23 };
25 template<class> struct is_update : std::false_type {};
26 template<class Member, class Value> struct is_update<update<Member, Value>> : std::true_type {};
27 template<class T> concept Update = is_update<T>::value;
29 template<class Member>
30 struct field {
31 field(Member member) : member(member) {}
33 template <typename Value>
34 update<Member, Value> operator=(Value value) const {
35 return {member, value};
36 }
38 Member member;
39 };
41 template<class Record>
42 class transaction {
43 Record& m_record;
45 bool all(auto... results) const {
46 return (... && results);
47 }
49 public:
50 transaction(Record& record) : m_record(record) {}
52 bool operator()(Update auto... updates) {
53 auto tmp = m_record;
55 if(all(updates(tmp)...)) {
56 std::swap(m_record, tmp);
57 return true;
58 }
60 return false;
61 }
62 };
64 template<typename Record>
65 auto with(Record& record) {
66 return transaction(record);
67 }
69 #include <iostream>
71 int main() {
72 struct person {
73 std::string name;
74 std::string surname;
75 unsigned age;
76 };
78 auto name = field { &person::name };
79 auto surname = field { &person::surname };
80 auto age = field { &person::age };
82 person martha;
83 with(martha) (
84 name = "Martha",
85 surname = "Jones",
86 age = 42
87 );
89 std::cout << martha.name << ' ' << martha.surname << ' ' << martha.age << std::endl;
90 }