zeus

Unnamed 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

Diffstat:
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;
}