История изменений
Исправление quasimoto, (текущая версия) :
#include <iostream>
struct Unit {};
template <typename T>
class IO;
using Void = IO<Unit>;
extern const Void done;
template <typename T>
class IO {
T const c;
public:
explicit IO(T const& c) : c(c) {}
friend T const unsafeRun(IO<T> const& io) { return io.c; }
friend Void print(IO<T> const& io) { std::cout << io.c << std::endl; return done; }
};
const Void done = Void(Unit());
template <typename T>
class Ref {
T v;
explicit Ref(T const& v) : v(v) {}
public:
template <typename U>
friend IO<Ref<U>> const make_ref(T const& v) { return IO<Ref<U>>(Ref<U>(v)); }
friend Void const operator+=(Ref<T>& r, T const& x) { r.v += x; return done; }
IO<T> const operator*() const { return IO<T>(v); }
};
Ref<int> counter = unsafeRun(make_ref<int>(0));
Void f(int x) {
counter += x;
return done;
}
IO<int> g() {
return *counter;
}
int main() {
f(2);
f(3);
auto x = g();
print(x);
}
Исходная версия quasimoto, :
#include <iostream>
struct unit {};
template <typename T>
class io {
T const c;
public:
explicit io(T const& c) : c(c) {}
friend T const unsafeRun(io<T> const& a) { return a.c; }
friend io<unit> print(io<T> const& a) { std::cout << a.c << std::endl; return io<unit>(unit()); }
};
template <typename T>
class ref {
T v;
explicit ref(T const& v) : v(v) {}
public:
template <typename U>
friend io<ref<U>> const make_ref(T const& v) { return io<ref<U>>(ref<U>(v)); }
friend io<unit> const operator+=(ref<T>& r, T const& x) { r.v += x; return io<unit>(unit()); }
io<T> const operator*() const { return io<T>(v); }
};
ref<int> counter = unsafeRun(make_ref<int>(0));
void f(int x) {
counter += x;
}
io<int> g() {
return *counter;
}
int main() {
f(2);
f(3);
auto x = g();
print(x);
}