diff --git a/external/optionalm/README b/external/optionalm/README
new file mode 100644
index 0000000000000000000000000000000000000000..206f59688c7a8d5687f53dec41e9db6af3340a61
--- /dev/null
+++ b/external/optionalm/README
@@ -0,0 +1 @@
+Adapted from github.com:halfflat/optionalm
diff --git a/external/optionalm/optionalm.h b/external/optionalm/optionalm.h
new file mode 100644
index 0000000000000000000000000000000000000000..d22c8ea27a4cd7304ae8becc6ebe373a355453c7
--- /dev/null
+++ b/external/optionalm/optionalm.h
@@ -0,0 +1,318 @@
+/*! \file optionalm.h
+ *  \brief An option class with a monadic interface.
+ *
+ *  The std::option<T> class was proposed for inclusion into C++14, but was
+ *  ultimately rejected. (See N3672 proposal for details.) This class offers
+ *  similar functionality, namely a class that can represent a value (or
+ *  reference), or nothing at all.
+ *
+ *  In addition, this class offers monadic and monoidal bindings, allowing
+ *  the chaining of operations any one of which might represent failure with
+ *  an unset optional value.
+ *
+ *  One point of difference between the proposal N3672 and this implementation
+ *  is the lack of constexpr versions of the methods and constructors.
+ */
+
+#ifndef HF_OPTIONALM_H_
+#define HF_OPTIONALM_H_
+
+#include <type_traits>
+#include <stdexcept>
+#include <utility>
+
+#include <optionalm/uninitialized.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wlogical-op-parentheses"
+
+namespace hf {
+namespace optionalm {
+
+template <typename X> struct optional;
+
+struct optional_unset_error: std::runtime_error {
+    explicit optional_unset_error(const std::string &what_str): std::runtime_error(what_str) {}
+    optional_unset_error(): std::runtime_error("optional value unset") {}
+};
+
+struct optional_invalid_dereference: std::runtime_error {
+    explicit optional_invalid_dereference(const std::string &what_str): std::runtime_error(what_str) {}
+    optional_invalid_dereference(): std::runtime_error("derefernce of optional<void> value") {}
+};
+
+struct nothing_t {};
+constexpr nothing_t nothing{};
+
+namespace detail {
+    template <typename Y> struct lift_type { typedef optional<Y> type; };
+    template <typename Y> struct lift_type<optional<Y>> { typedef optional<Y> type; };
+
+    struct optional_tag {};
+
+    template <typename X> struct is_optional {
+        enum {value=std::is_base_of<optional_tag,typename std::decay<X>::type>::value };
+    };
+
+    template <typename D,typename X> struct wrapped_type_ { typedef X type; };
+    template <typename D,typename X> struct wrapped_type_<optional<D>,X> { typedef D type; };
+
+    template <typename X> struct wrapped_type { typedef typename wrapped_type_<typename std::decay<X>::type,X>::type type; };
+
+    template <typename X>
+    struct optional_base: detail::optional_tag {
+        template <typename Y> friend struct optional;
+
+    protected:
+        typedef hf::optionalm::uninitialized<X> D;
+
+    public:
+        typedef typename D::reference_type reference_type;
+        typedef typename D::const_reference_type const_reference_type;
+        typedef typename D::pointer_type pointer_type;
+        typedef typename D::const_pointer_type const_pointer_type;
+
+    protected:
+        bool set;
+        D data;
+
+        optional_base(): set(false) {}
+
+        template <typename T>
+        optional_base(bool set_,T&& init): set(set_) { if (set) data.construct(std::forward<T>(init)); }
+
+        reference_type ref() { return data.ref(); }
+        const_reference_type ref() const { return data.cref(); }
+
+    public:
+        ~optional_base() { if (set) data.destruct(); }
+
+        const_pointer_type operator->() const { return data.ptr(); }
+        pointer_type operator->() { return data.ptr(); }
+            
+        const_reference_type operator*() const { return ref(); }
+        reference_type operator*() { return ref(); }
+            
+        reference_type get() {
+            if (set) return ref();
+            else throw optional_unset_error();
+        }
+
+        const_reference_type get() const {
+            if (set) return ref();
+            else throw optional_unset_error();
+        }
+
+        explicit operator bool() const { return set; }
+
+        template <typename Y>
+        bool operator==(const Y &y) const { return set && ref()==y; }
+
+        template <typename Y>
+        bool operator==(const optional<Y> &o) const {
+            return set && o.set && ref()==o.ref() || !set && !o.set;
+        }
+
+        void reset() {
+            if (set) data.destruct();
+            set=false;
+        }
+
+        template <typename F>
+        auto bind(F &&f) -> typename lift_type<decltype(data.apply(std::forward<F>(f)))>::type {
+            typedef decltype(data.apply(std::forward<F>(f))) F_result_type;
+            typedef typename lift_type<F_result_type>::type result_type;
+
+            if (!set) return result_type();
+            else return bind_impl<result_type,std::is_same<F_result_type,void>::value>::bind(data,std::forward<F>(f));
+        }
+
+        template <typename F>
+        auto bind(F &&f) const -> typename lift_type<decltype(data.apply(std::forward<F>(f)))>::type {
+            typedef decltype(data.apply(std::forward<F>(f))) F_result_type;
+            typedef typename lift_type<F_result_type>::type result_type;
+
+            if (!set) return result_type();
+            else return bind_impl<result_type,std::is_same<F_result_type,void>::value>::bind(data,std::forward<F>(f));
+        }
+
+        template <typename F>
+        auto operator>>(F &&f) -> decltype(this->bind(std::forward<F>(f))) { return bind(std::forward<F>(f)); }
+
+        template <typename F>
+        auto operator>>(F &&f) const -> decltype(this->bind(std::forward<F>(f))) { return bind(std::forward<F>(f)); }
+
+    private:
+        template <typename R,bool F_void_return>
+        struct bind_impl {
+            template <typename DT,typename F>
+            static R bind(DT &d,F &&f) { return R(d.apply(std::forward<F>(f))); }
+        };
+
+        template <typename R>
+        struct bind_impl<R,true> {
+            template <typename DT,typename F>
+            static R bind(DT &d,F &&f) { d.apply(std::forward<F>(f)); return R(true); }
+        };
+        
+    };
+}
+
+template <typename X>
+struct optional: detail::optional_base<X> {
+    typedef detail::optional_base<X> base;
+    using base::set;
+    using base::ref;
+    using base::reset;
+    using base::data;
+
+    optional(): base() {}
+    optional(nothing_t): base() {}
+
+    template <typename Y=X,typename = typename std::enable_if<std::is_copy_constructible<Y>::value>::type>
+    optional(const X &x): base(true,x) {}
+
+    template <typename Y=X,typename = typename std::enable_if<std::is_move_constructible<Y>::value>::type>
+    optional(X &&x): base(true,std::move(x)) {}
+
+    optional(const optional &ot): base(ot.set,ot.ref()) {}
+
+    template <typename T>
+    optional(const optional<T> &ot): base(ot.set,ot.ref()) {}
+
+    optional(optional &&ot): base(ot.set,std::move(ot.ref())) {}
+
+    template <typename T>
+    optional(optional<T> &&ot): base(ot.set,std::move(ot.ref())) {}
+
+    template <typename Y,typename = typename std::enable_if<!detail::is_optional<Y>::value>::type>
+    optional &operator=(Y &&y) {
+        if (set) ref()=std::forward<Y>(y);
+        else {
+            set=true;
+            data.construct(std::forward<Y>(y));
+        }
+        return *this;
+    }
+
+    optional &operator=(const optional &o) {
+        if (set) {
+            if (o.set) ref()=o.ref();
+            else reset();
+        }
+        else {
+            set=o.set;
+            if (set) data.construct(o.ref());
+        }
+        return *this;
+    }
+
+    template <typename Y=X, typename =typename std::enable_if<
+        std::is_move_assignable<Y>::value &&
+        std::is_move_constructible<Y>::value
+    >::type>
+    optional &operator=(optional &&o) {
+        if (set) {
+            if (o.set) ref()=std::move(o.ref());
+            else reset();
+        }
+        else {
+            set=o.set;
+            if (set) data.construct(std::move(o.ref()));
+        }
+        return *this;
+    }
+};
+
+template <typename X>
+struct optional<X &>: detail::optional_base<X &> {
+    typedef detail::optional_base<X &> base;
+    using base::set;
+    using base::ref;
+    using base::data;
+
+    optional(): base() {}
+    optional(nothing_t): base() {}
+    optional(X &x): base(true,x) {}
+
+    template <typename T>
+    optional(optional<T &> &ot): base(ot.set,ot.ref()) {}
+
+    template <typename Y,typename = typename std::enable_if<!detail::is_optional<Y>::value>::type>
+    optional &operator=(Y &y) {
+        set=true;
+        ref()=y;
+        return *this;
+    }
+
+    template <typename Y>
+    optional &operator=(optional<Y &> &o) {
+        set=o.set;
+        data.construct(o);
+        return *this;
+    }
+};
+
+
+/* special case for optional<void>, used as e.g. the result of
+ * binding to a void function */
+
+template <>
+struct optional<void>: detail::optional_base<void> {
+    typedef detail::optional_base<void> base;
+    using base::set;
+
+    optional(): base() {}
+
+    template <typename T>
+    optional(T): base(true,true) {}
+
+    template <typename T>
+    optional(const optional<T> &o): base(o.set,true) {}
+    
+    template <typename T>
+    optional &operator=(T) { set=true; return *this; }
+
+    template <typename T>
+    optional &operator=(const optional<T> &o) { set=o.set; return *this; }
+
+    // override equality operators
+    template <typename Y>
+    bool operator==(const Y &y) const { return false; }
+
+    bool operator==(const optional<void> &o) const {
+        return set && o.set || !set && !o.set;
+    }
+};
+
+
+template <typename A,typename B>
+typename std::enable_if<
+    detail::is_optional<A>::value || detail::is_optional<B>::value,
+    optional<typename std::common_type<typename detail::wrapped_type<A>::type,typename detail::wrapped_type<B>::type>::type>
+>::type
+operator|(A &&a,B &&b) {
+    typedef typename std::common_type<typename detail::wrapped_type<A>::type,typename detail::wrapped_type<B>::type>::type common;
+    return a?a:b;
+}
+
+template <typename A,typename B>
+typename std::enable_if<
+    detail::is_optional<A>::value || detail::is_optional<B>::value,
+    optional<typename detail::wrapped_type<B>::type>
+>::type
+operator&(A &&a,B &&b) {
+    typedef optional<typename detail::wrapped_type<B>::type> result_type;
+    return a?b:result_type();
+}
+
+inline optional<void> provided(bool condition) { return condition?optional<void>(true):optional<void>(); }
+
+template <typename X>
+optional<X> just(X &&x) { return optional<X>(std::forward<X>(x)); }
+
+}} // namespace hf::optionalm
+
+#pragma clang diagnostic pop
+
+#endif // ndef HF_OPTIONALM_H_
diff --git a/external/optionalm/uninitialized.h b/external/optionalm/uninitialized.h
new file mode 100644
index 0000000000000000000000000000000000000000..264e3844bc9b21e3f6af44c92fa588141f517ac0
--- /dev/null
+++ b/external/optionalm/uninitialized.h
@@ -0,0 +1,175 @@
+/*! \file uninitialized.h
+ *  \brief Represent a possibly-uninitialized value, reference or void.
+ *
+ *  The \c uninitialized\<X\> structure holds space for an item of
+ *  type \c X, leaving its construction or destruction to the user.
+ */
+
+#ifndef HF_UNINITIALIZED_H_
+#define HF_UNINITIALIZED_H_
+
+namespace hf {
+namespace optionalm {
+
+/*! \defgroup uninitialized The uninitialized<X> classes.
+ *  \{
+ * 
+ *  The \c uninitialized\<X\> structure holds space for an item of
+ *  type \c X, which can then be explicitly constructed or
+ *  deconstructed through the \c construct() and \c destruct()
+ *  member functions.
+ *
+ *  Specialisations for reference types <tt>X &</tt> and for the
+ *  \c void type allow handling non-value types in a uniform
+ *  manner.
+ */
+
+/*! \brief Maintains storage for a value of type X, with explicit
+ *  construction and destruction.
+ *
+ *  \tparam X
+ *      The wrapped value type.
+ */
+template <typename X>
+struct uninitialized {
+private:
+    typename std::aligned_storage<sizeof(X),alignof(X)>::type data;
+
+public:
+    //! &nbsp;
+    typedef X *pointer_type;
+    //! &nbsp;
+    typedef const X *const_pointer_type;
+    //! &nbsp;
+    typedef X &reference_type;
+    //! &nbsp;
+    typedef const X &const_reference_type;
+
+    //! Return a pointer to the value.
+    pointer_type ptr() { return reinterpret_cast<X *>(&data); }
+    //! Return a const pointer to the value.
+    const_pointer_type cptr() const { return reinterpret_cast<const X *>(&data); }
+
+    //! Return a reference to the value.
+    reference_type ref() { return *reinterpret_cast<X *>(&data); }
+    //! Return a const reference to the value.
+    const_reference_type cref() const { return *reinterpret_cast<const X *>(&data); }
+
+    //! Copy construct the value.
+    template <typename Y=X,typename =typename std::enable_if<std::is_copy_constructible<Y>::value>::type>
+    void construct(const X &x) { new(&data) X(x); }
+
+    //! General constructor
+    template <typename... Y,typename =typename std::enable_if<std::is_constructible<X,Y...>::value>::type>
+    void construct(Y&& ...args) { new(&data) X(std::forward<Y>(args)...); }
+
+    //! Call the destructor of the value.
+    void destruct() { ptr()->~X(); }
+
+    //! Apply the one-parameter functor F to the value by reference.
+    template <typename F>
+    typename std::result_of<F(reference_type)>::type apply(F &&f) { return f(ref()); }
+    //! Apply the one-parameter functor F to the value by const reference.
+    template <typename F>
+    typename std::result_of<F(const_reference_type)>::type apply(F &&f) const { return f(cref()); }
+};
+
+/*! \brief Maintains storage for a pointer of type X, representing
+ *  a possibly uninitialized reference.
+ *
+ *  \tparam X& 
+ *      Wrapped reference type.
+ */
+template <typename X>
+struct uninitialized<X&> {
+private:
+    X *data;
+
+public:
+    //! &nbsp;
+    typedef X *pointer_type;
+    //! &nbsp;
+    typedef const X *const_pointer_type;
+    //! &nbsp;
+    typedef X &reference_type;
+    //! &nbsp;
+    typedef const X &const_reference_type;
+
+    //! Return a pointer to the value.
+    pointer_type ptr() { return data; }
+    //! Return a const pointer to the value.
+    const_pointer_type cptr() const { return data; }
+
+    //! Return a reference to the value.
+    reference_type ref() { return *data; }
+    //! Return a const reference to the value.
+    const_reference_type cref() const { return *data; }
+
+    //! Set the reference data.
+    void construct(X &x) { data=&x; }
+    //! Destruct is a NOP for reference data.
+    void destruct() {}
+
+    //! Apply the one-parameter functor F to the value by reference.
+    template <typename F>
+    typename std::result_of<F(reference_type)>::type apply(F &&f) { return f(ref()); }
+    //! Apply the one-parameter functor F to the value by const reference.
+    template <typename F>
+    typename std::result_of<F(const_reference_type)>::type apply(F &&f) const { return f(cref()); }
+};
+
+/*! \brief Wrap a void type in an uninitialized template.
+ * 
+ *  Allows the use of <tt>uninitialized\<X\></tt> for void \c X, for generic
+ *  applications.
+ */
+
+template <>
+struct uninitialized<void> {
+    //! &nbsp;
+    typedef void *pointer_type;
+    //! &nbsp;
+    typedef const void *const_pointer_type;
+    //! &nbsp;
+    typedef void reference_type;
+    //! &nbsp;
+    typedef void const_reference_type;
+
+    //! &nbsp;
+    pointer_type ptr() { return nullptr; }
+    //! &nbsp;
+    const_pointer_type cptr() const { return nullptr; }
+
+    //! &nbsp;
+    reference_type ref() {}
+    //! &nbsp;
+    const_reference_type cref() const {}
+
+    //! No operation.
+    void construct(...) {}
+    //! No operation.
+    void destruct() {}
+
+    //! Equivalent to <tt>f()</tt>
+    template <typename F>
+    typename std::result_of<F()>::type apply(F &&f) const { return f(); }
+};
+
+template <typename...>
+struct uninitialized_can_construct: std::false_type {};
+
+template <typename X,typename... Y>
+struct uninitialized_can_construct<X,Y...>: std::integral_constant<bool,std::is_constructible<X,Y...>::value> {};
+
+template <typename X,typename Y>
+struct uninitialized_can_construct<X &,Y>: std::integral_constant<bool,std::is_convertible<X &,Y>::value> {};
+
+template <typename... Y>
+struct uninitialized_can_construct<void,Y...>: std::true_type {};
+
+/*! \} */
+
+}} // namespace hf::optionalm
+
+#endif // ndef HF_UNINITIALIZED_H_
+
diff --git a/src/event_queue.hpp b/src/event_queue.hpp
index 0a8b33707a2d82e949717fd243479ce33776120e..80b14a892c1cbafa0d39ba2a337d37190f98f873 100644
--- a/src/event_queue.hpp
+++ b/src/event_queue.hpp
@@ -1,9 +1,10 @@
 #pragma once
 
+#include <cstdint>
 #include <ostream>
 #include <queue>
 
-#include <cstdint>
+#include <optionalm/optionalm.h>
 
 namespace nest {
 namespace mc {
@@ -45,14 +46,14 @@ public :
     }
 
     // pop until
-    std::pair<bool, local_event> pop_if_before(float t_until) {
+    hf::optionalm::optional<local_event> pop_if_before(float t_until) {
          if (!queue_.empty() && queue_.top().time < t_until) {
              auto ev = queue_.top();
              queue_.pop();
-             return {true, ev};
+             return ev;
          }
          else {
-             return {false, {}};
+             return hf::optionalm::nothing;
          }
     }
 
diff --git a/src/fvm.hpp b/src/fvm.hpp
index 4a908bba49887948e37bfa7fe3409b19df90bbb3..49d0af7a7ea2a24a486eb99f1d80079605ad5889 100644
--- a/src/fvm.hpp
+++ b/src/fvm.hpp
@@ -19,6 +19,7 @@
 #include <util.hpp>
 
 #include <vector/include/Vector.hpp>
+#include <optionalm/optionalm.h>
 
 #include <mechanisms/expsyn.hpp>
 
@@ -510,18 +511,14 @@ void fvm_cell<T, I>::advance_to(T tfinal, T dt)
     }
 
     do {
-        auto tnext = std::min(tfinal, t_+dt);
-        auto next = events_.pop_if_before(tnext);
-        // if there is an event before tnext...
-        if(next.first) {
-            tnext = next.second.time;
-        }
+        auto tstep = std::min(tfinal, t_+dt);
+        auto next = events_.pop_if_before(tstep);
+        auto tnext = next? next->time: tstep;
+
         advance(tnext-t_);
         t_ = tnext;
-        if(next.first) { // handle event
-            auto &e = next.second;
-
-            mechanisms_[synapse_index_]->net_receive(e.target, e.weight);
+        if (next) { // handle event
+            mechanisms_[synapse_index_]->net_receive(next->target, next->weight);
         }
     } while(t_<tfinal);
 }
diff --git a/tests/test_event_queue.cpp b/tests/test_event_queue.cpp
index 3297784d506f6eff10078e249388942b85d2240f..e67ade0bea22a417ca417a78c550b67bb0c3e45b 100644
--- a/tests/test_event_queue.cpp
+++ b/tests/test_event_queue.cpp
@@ -18,7 +18,7 @@ TEST(event_queue, push)
     std::vector<float> times;
     while(q.size()) {
         times.push_back(
-            q.pop_if_before(std::numeric_limits<float>::max()).second.time
+            q.pop_if_before(std::numeric_limits<float>::max())->time
         );
     }
 
@@ -44,7 +44,7 @@ TEST(event_queue, push_range)
     std::vector<float> times;
     while(q.size()) {
         times.push_back(
-            q.pop_if_before(std::numeric_limits<float>::max()).second.time
+            q.pop_if_before(std::numeric_limits<float>::max())->time
         );
     }
 
@@ -68,26 +68,26 @@ TEST(event_queue, pop_if_before)
     EXPECT_EQ(q.size(), 4u);
 
     auto e1 = q.pop_if_before(0.);
-    EXPECT_FALSE(e1.first);
+    EXPECT_FALSE(e1);
     EXPECT_EQ(q.size(), 4u);
 
     auto e2 = q.pop_if_before(5.);
-    EXPECT_TRUE(e2.first);
-    EXPECT_EQ(e2.second.target, 1u);
+    EXPECT_TRUE(e2);
+    EXPECT_EQ(e2->target, 1u);
     EXPECT_EQ(q.size(), 3u);
 
     auto e3 = q.pop_if_before(5.);
-    EXPECT_TRUE(e3.first);
-    EXPECT_EQ(e3.second.target, 2u);
+    EXPECT_TRUE(e3);
+    EXPECT_EQ(e3->target, 2u);
     EXPECT_EQ(q.size(), 2u);
 
     auto e4 = q.pop_if_before(2.5);
-    EXPECT_FALSE(e4.first);
+    EXPECT_FALSE(e4);
     EXPECT_EQ(q.size(), 2u);
 
     auto e5 = q.pop_if_before(5.);
-    EXPECT_TRUE(e5.first);
-    EXPECT_EQ(e5.second.target, 3u);
+    EXPECT_TRUE(e5);
+    EXPECT_EQ(e5->target, 3u);
     EXPECT_EQ(q.size(), 1u);
 
     q.pop_if_before(5.);
@@ -95,5 +95,5 @@ TEST(event_queue, pop_if_before)
 
     // empty queue should always return "false"
     auto e6 = q.pop_if_before(100.);
-    EXPECT_FALSE(e6.first);
+    EXPECT_FALSE(e6);
 }