diff --git a/arbor/include/arbor/util/optional.hpp b/arbor/include/arbor/util/optional.hpp
index f36d3b3947c84c53a22f7aedd14166613508c095..e15d5addfc8bedeff0e77bb8115fa3aee4558d9f 100644
--- a/arbor/include/arbor/util/optional.hpp
+++ b/arbor/include/arbor/util/optional.hpp
@@ -107,6 +107,7 @@ namespace detail {
         using const_rvalue_reference = typename data_type::const_rvalue_reference;
 
     public:
+        using value_type = X;
         using reference = typename data_type::reference;
         using const_reference = typename data_type::const_reference;
         using pointer = typename data_type::pointer;
@@ -165,6 +166,15 @@ namespace detail {
             }
             set = false;
         }
+
+        template <typename Y>
+        void emplace(Y&& y) {
+            if (set) {
+                data.destruct();
+            }
+            data.construct(std::forward<Y>(y));
+            set = true;
+        }
     };
 
     // type utilities
diff --git a/test/unit/test_optional.cpp b/test/unit/test_optional.cpp
index c14b34de4808a861ddd05de16176ecbec9c4a3e8..760e4a683a1d2ab7d8b64823c2c3323360b266f3 100644
--- a/test/unit/test_optional.cpp
+++ b/test/unit/test_optional.cpp
@@ -287,3 +287,18 @@ TEST(optional, just) {
     EXPECT_EQ(3, o2.value());
     EXPECT_EQ(4, o3.value());
 }
+
+TEST(optional, emplace) {
+    optional<int> o1(7);
+    optional<std::array<double, 3>> o2{{22., 22., 22.}};
+    int x = 42;
+    std::array<double, 3> arr{{4.5, 7.1, 1.2}};
+
+    o1.emplace(x);
+    o2.emplace(arr);
+
+    EXPECT_EQ(42, o1.value());
+    EXPECT_EQ(4.5, o2.value()[0]);
+    EXPECT_EQ(7.1, o2.value()[1]);
+    EXPECT_EQ(1.2, o2.value()[2]);
+}