diff --git a/src/util/nop.hpp b/src/util/nop.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6ec568b9d5fe9bfe4904b23ea6babcdf8b4ca84e
--- /dev/null
+++ b/src/util/nop.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+/*
+ * Provide object that implicitly converts to
+ * a std::function object that does nothing but return a
+ * default-constructed type or void.
+ */
+
+#include <functional>
+
+namespace nest {
+namespace mc {
+namespace util {
+
+struct nop_function_t {
+    template <typename R, typename... Args>
+    operator std::function<R (Args...)>() const {
+        return [](Args...) { return R{}; };
+    }
+
+    template <typename... Args>
+    operator std::function<void (Args...)>() const {
+        return [](Args...) { };
+    }
+
+    // keep clang happy: see CWG issue #253,
+    // http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#253
+    constexpr nop_function_t() {}
+};
+
+static constexpr nop_function_t nop_function;
+
+} // namespace util
+} // namespace mc
+} // namespace nest
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index fb1b9369d4e38498c8953fc0ce2f16c1dbc715dc..83c537b26385b62ece833d59931ece57bc1cd8cc 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -21,6 +21,7 @@ set(TEST_SOURCES
     test_mask_stream.cpp
     test_matrix.cpp
     test_mechanisms.cpp
+    test_nop.cpp
     test_optional.cpp
     test_parameters.cpp
     test_point.cpp
diff --git a/tests/unit/test_nop.cpp b/tests/unit/test_nop.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3571ad827555e23040658f3f7275f3bcf53d9d0
--- /dev/null
+++ b/tests/unit/test_nop.cpp
@@ -0,0 +1,75 @@
+#include "gtest.h"
+#include "util/nop.hpp"
+
+using namespace nest::mc::util;
+
+TEST(nop, void_fn) {
+    std::function<void ()> f{nop_function};
+
+    EXPECT_TRUE(f);
+    f(); // should do nothing
+
+    bool flag = false;
+    f = [&]() { flag = true; };
+    f();
+    EXPECT_TRUE(flag);
+
+    flag = false;
+    f = nop_function;
+    f();
+    EXPECT_FALSE(flag);
+
+    // with some arguments
+    std::function<void (int, int)> g{nop_function};
+    EXPECT_TRUE(g);
+    g(2, 3); // should do nothing
+
+    int sum = 0;
+    g = [&](int a, int b) { sum = a+b; };
+    g(2, 3);
+    EXPECT_EQ(5, sum);
+
+    sum = 0;
+    g = nop_function;
+    g(2, 3);
+    EXPECT_EQ(0, sum);
+}
+
+struct check_default {
+    int value = 100;
+
+    check_default() = default;
+    explicit check_default(int n): value(n) {}
+};
+
+TEST(nop, default_return_fn) {
+    std::function<check_default ()> f{nop_function};
+
+    EXPECT_TRUE(f);
+    auto result = f();
+    EXPECT_EQ(result.value, 100);
+
+    f = []() { return check_default(17); };
+    result = f();
+    EXPECT_EQ(result.value, 17);
+
+    f = nop_function;
+    result = f();
+    EXPECT_EQ(result.value, 100);
+
+    std::function<check_default (double, double)> g{nop_function};
+
+    EXPECT_TRUE(g);
+    result = g(1.4, 1.5);
+    EXPECT_EQ(result.value, 100);
+
+    g = [](double x, double y) { return check_default{(int)(x*y)}; };
+    result = g(1.4, 1.5);
+    EXPECT_EQ(result.value, 2);
+
+    g = nop_function;
+    result = g(1.4, 1.5);
+    EXPECT_EQ(result.value, 100);
+
+}
+