From c0b1ee066512413cc7a824925c074ef8d34ed7dc Mon Sep 17 00:00:00 2001 From: Sam Yates <halfflat@gmail.com> Date: Tue, 23 Jun 2020 09:07:08 +0200 Subject: [PATCH] Fix event_generator constructor. (#1067) * Guard `event_generator` implicit constructor with type test. * Fix linking error from use of `empty_generator` by replacing pointers to `no_event` with nullptr. * Clarify `regular_generator` semantics in comment. * Add unit test for checking. Fixes #1066 --- arbor/include/arbor/event_generator.hpp | 11 ++++--- test/unit/test_event_generators.cpp | 38 +++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/arbor/include/arbor/event_generator.hpp b/arbor/include/arbor/event_generator.hpp index ecd0e476..8d12a218 100644 --- a/arbor/include/arbor/event_generator.hpp +++ b/arbor/include/arbor/event_generator.hpp @@ -4,6 +4,7 @@ #include <cstdint> #include <memory> #include <random> +#include <type_traits> #include <arbor/assert.hpp> #include <arbor/common_types.hpp> @@ -61,18 +62,15 @@ using event_seq = std::pair<const spike_event*, const spike_event*>; struct empty_generator { void reset() {} event_seq events(time_type, time_type) { - return {&no_event, &no_event}; + return {nullptr, nullptr}; } - -private: - static spike_event no_event; }; class event_generator { public: event_generator(): event_generator(empty_generator()) {} - template <typename Impl> + template <typename Impl, std::enable_if_t<!std::is_same<std::decay_t<Impl>, event_generator>::value, int> = 0> event_generator(Impl&& impl): impl_(new wrap<Impl>(std::forward<Impl>(impl))) {} @@ -128,6 +126,7 @@ private: }; }; +// Convenience routines for making schedule_generator: // Generate events with a fixed target and weight according to // a provided time schedule. @@ -161,7 +160,7 @@ private: schedule sched_; }; -// Convenience routines for making schedule_generator: +// Generate events at integer multiples of dt that lie between tstart and tstop. inline event_generator regular_generator( cell_member_type target, diff --git a/test/unit/test_event_generators.cpp b/test/unit/test_event_generators.cpp index d79eb423..032abda3 100644 --- a/test/unit/test_event_generators.cpp +++ b/test/unit/test_event_generators.cpp @@ -1,5 +1,7 @@ #include "../gtest.h" +#include <utility> + #include <arbor/event_generator.hpp> #include <arbor/spike_event.hpp> @@ -15,8 +17,40 @@ namespace{ } } +TEST(event_generators, assign_and_copy) { + event_generator gen = regular_generator({1, 2}, 5., 0.5, 0.75); + spike_event expected{{1, 2}, 0.75, 5.}; + + auto first = [](const event_seq& seq) { + if (seq.first==seq.second) throw std::runtime_error("no events"); + return *seq.first; + }; + + ASSERT_EQ(expected, first(gen.events(0., 1.))); + gen.reset(); + + event_generator g1(gen); + EXPECT_EQ(expected, first(g1.events(0., 1.))); + + event_generator g2; + g2 = gen; + EXPECT_EQ(expected, first(g2.events(0., 1.))); + + const auto& const_gen = gen; + + event_generator g3(const_gen); + EXPECT_EQ(expected, first(g3.events(0., 1.))); + + event_generator g4; + g4 = gen; + EXPECT_EQ(expected, first(g4.events(0., 1.))); + + event_generator g5(std::move(gen)); + EXPECT_EQ(expected, first(g5.events(0., 1.))); +} + TEST(event_generators, regular) { - // make a regular generator that generates its first event at t=2ms and subsequent + // Make a regular generator that generates its first event at t=2ms and subsequent // events regularly spaced 0.5 ms apart. time_type t0 = 2.0; time_type dt = 0.5; @@ -25,7 +59,7 @@ TEST(event_generators, regular) { event_generator gen = regular_generator(target, weight, t0, dt); - // helper for building a set of + // Helper for building a set of expected events. auto expected = [&] (std::vector<time_type> times) { pse_vector events; for (auto t: times) { -- GitLab