zeusUnnamed repository; edit this file 'description' to name the repository. |
git clone Unknown |
Log | Files | Refs |
commit | 99df392c5bab4cf9cd7cb54d381f0036593d0253 |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Sun, 11 May 2025 21:06:25 +0200 |
DSL for atomic transactions
A | dsl_transactions.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 files changed, 92 insertions(+), 0 deletions(-)
diff --git a/ dsl_transactions.cpp b/ dsl_transactions.cpp
@@ -0,0 +1,92 @@
#include <utility>
#include <functional>
#include <string>
template<class Member, class Value>
struct update {
update(Member member, Value value) : member(member), value(value) {}
template<typename Record>
bool operator()(Record& record) {
if constexpr(std::is_invocable_r<bool, Member, Record, Value>()) {
return std::invoke(member, record, value);
} else if constexpr (std::is_invocable<Member, Record, Value>()) {
std::invoke(member, record, value);
return true;
} else {
std::invoke(member, record) = value;
return true;
}
}
Member member;
Value value;
};
template<class> struct is_update : std::false_type {};
template<class Member, class Value> struct is_update<update<Member, Value>> : std::true_type {};
template<class T> concept Update = is_update<T>::value;
template<class Member>
struct field {
field(Member member) : member(member) {}
template <typename Value>
update<Member, Value> operator=(Value value) const {
return {member, value};
}
Member member;
};
template<class Record>
class transaction {
Record& m_record;
bool all(auto... results) const {
return (... && results);
}
public:
transaction(Record& record) : m_record(record) {}
bool operator()(Update auto... updates) {
auto tmp = m_record;
if(all(updates(tmp)...)) {
std::swap(m_record, tmp);
return true;
}
return false;
}
};
template<typename Record>
auto with(Record& record) {
return transaction(record);
}
#include <iostream>
int main() {
struct person {
std::string name;
std::string surname;
unsigned age;
};
auto name = field { &person::name };
auto surname = field { &person::surname };
auto age = field { &person::age };
person martha;
with(martha) (
name = "Martha",
surname = "Jones",
age = 42
);
std::cout << martha.name << ' ' << martha.surname << ' ' << martha.age << std::endl;
}