Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rust-like Ownership and Reference
#include <atomic>
#include <cassert>
#include <iostream>
using namespace std;
template <class T>
class MutableRef;
template <class T>
class ImmutableRef;
template <class T>
class OwnerPointer {
private:
T *rep_ = nullptr;
atomic<int> ref_;
public:
OwnerPointer(T *rep = nullptr) : rep_(rep), ref_(0) {}
~OwnerPointer() { delete rep_; }
OwnerPointer(const OwnerPointer<T> &other) = delete;
OwnerPointer(OwnerPointer<T> &&other) { swap(rep_, other.rep_); }
operator T *() { return rep_; }
OwnerPointer &operator=(const OwnerPointer<T> &other) = delete;
OwnerPointer &operator=(OwnerPointer<T> &&other) {
swap(rep_, other.rep_);
return *this;
}
MutableRef<T> RefMutable();
ImmutableRef<T> RefImmutable();
private:
friend class MutableRef<T>;
void UnrefMutable() { ++ref_; }
friend class ImmutableRef<T>;
void UnrefImmutable() { --ref_; }
};
template <class T>
class ImmutableRef {
private:
OwnerPointer<T> *rep_;
private:
friend class OwnerPointer<T>;
ImmutableRef(OwnerPointer<T> *rep) : rep_(rep) {}
public:
~ImmutableRef() { rep_->UnrefImmutable(); }
operator const T *() { return rep_->rep_; }
};
template <class T>
class MutableRef {
private:
OwnerPointer<T> *rep_;
private:
friend class OwnerPointer<T>;
MutableRef(OwnerPointer<T> *rep) : rep_(rep) {}
public:
~MutableRef() { rep_->UnrefMutable(); }
operator T *() { return rep_->rep_; }
};
template <class T>
ImmutableRef<T> OwnerPointer<T>::RefImmutable() {
assert(ref_ >= 0);
++ref_;
return ImmutableRef<T>(this);
}
template <class T>
MutableRef<T> OwnerPointer<T>::RefMutable() {
assert(ref_ == 0);
--ref_;
return MutableRef<T>(this);
}
template <class T, class... Args>
OwnerPointer<T> make_owner(Args &&... args) {
return OwnerPointer<T>(new T(std::forward<Args>(args)...));
}
int main() {
auto owner1 = make_owner<int>(20);
printf("Owner1: %d\n", *owner1);
auto owner2 = std::move(owner1);
printf("Owner2: %d\n", *owner2);
OwnerPointer<int> owner3;
owner3 = std::move(owner2);
printf("Owner3: %d\n", *owner3);
{
auto immutable1 = owner3.RefImmutable();
printf("Immutable1: %d\n", *immutable1);
// *immutable1 = 30; // Err
auto immutable2 = owner3.RefImmutable();
printf("Immutable2: %d\n", *immutable2);
}
{
auto mutable1 = owner3.RefMutable();
printf("Mutable1: %d\n", *mutable1);
*mutable1 = 30; // Err
printf("Mutable1: %d\n", *mutable1);
// auto immutable1 = owner3.RefImmutable(); // Err
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.