LINUX.ORG.RU

История изменений

Исправление 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);
}