diff --git a/miniapp/io.cpp b/miniapp/io.cpp index 6267961b2937d209e1af2618551ab86bbdca130f..6b81a62c853fbc2098d343c0c61b926903f47c52 100644 --- a/miniapp/io.cpp +++ b/miniapp/io.cpp @@ -13,10 +13,13 @@ #include "io.hpp" // Let TCLAP understand value arguments that are of an optional type. -template <typename V> -struct TCLAP::ArgTraits<nest::mc::util::optional<V>> { - using ValueCategory = ValueLike; -}; + +namespace TCLAP { + template <typename V> + struct ArgTraits<nest::mc::util::optional<V>> { + using ValueCategory = ValueLike; + }; +} namespace nest { namespace mc { diff --git a/src/util/nop.hpp b/src/util/nop.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8315e93fbb467c7c3393656be79d09f372a76f66 --- /dev/null +++ b/src/util/nop.hpp @@ -0,0 +1,29 @@ +#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 { + +static 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...) { }; + } +} 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..cf131d9e5484503f2de5c34a73673a579534f98c --- /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); + +} +