#include <cstdio>
template <typename T>
struct const_ref;
template <typename T>
struct mut_ref;
struct unsafe_op {};
template <typename T>
struct safe_ptr {
long refcnt;
T *data;
safe_ptr() : refcnt(0), data(new T) {}
safe_ptr(T val) : refcnt(0), data(new T) {
*data = val;
}
~safe_ptr() { delete data; }
safe_ptr(safe_ptr const&) = delete;
const_ref<T> operator &() {
if (refcnt >= 0)
return const_ref<T>{this};
else
throw unsafe_op{};
}
mut_ref<T> operator +() {
if (refcnt == 0)
return mut_ref<T>{this};
else
throw unsafe_op{};
}
};
template <typename T>
struct const_ref {
safe_ptr<T>& ptr;
const_ref(safe_ptr<T> *upstream)
: ptr(*upstream) {
ptr.refcnt += 1;
}
~const_ref() {
ptr.refcnt -= 1;
}
T const& operator *() {
return *ptr.data;
}
};
template <typename T>
struct mut_ref {
safe_ptr<T>& ptr;
mut_ref(safe_ptr<T> *upstream)
: ptr(*upstream) {
ptr.refcnt -= 1;
}
~mut_ref() {
ptr.refcnt += 1;
}
T& operator *() {
return *ptr.data;
}
};
int main() {
safe_ptr<int> x { 1 };
{
auto ref = &x;
// *ref = 100; // would fail for modification of const
auto ref2 = &x;
printf("%i", *ref, *ref2);
// auto mut_ref = +x; // would fail for taking mutable ref while const refs exist
}
{
auto mut_ref = +x;
*mut_ref = 10;
}
{
auto ref = &x;
printf("%i", *ref);
}
}
Comments