@@ -19,16 +19,16 @@ namespace mpm
1919 // ! \ingroup Concepts
2020 // ! \{
2121 // !
22- // ! An instance of any class type can be published as an event. This
23- // ! definition precludes the publication of (for example) an int.
22+ // ! An instance of any C++ object type. That is, anything but a function,
23+ // ! reference, or void type
2424 // !
2525 // ! \par Requirements
2626 // ! Given:\n
2727 // ! E, an implementation of the Event concept
2828 // !
29- // ! |Expression | Requirements | Return type |
30- // ! |:-------------------------------|: -----------------------|:-------------------|
31- // ! |std::is_class <E>::value == true | E must be a class type | bool, must be true |
29+ // ! |Expression | Requirements | Return type |
30+ // ! |:--------------------------------|:-- -----------------------|:-------------------|
31+ // ! |std::is_object <E>::value == true | E must be an object type | bool, must be true |
3232 // ! \}
3333
3434 // ! \defgroup EventHandler
@@ -57,6 +57,30 @@ namespace mpm
5757
5858 namespace detail
5959 {
60+ // ! Adapts an instance of the Event concept into the
61+ // ! class hierarchy rooted at mpm::detail::event
62+ template <typename Event>
63+ class adapted_event : public detail ::event
64+ {
65+ public:
66+ using dispatch_as = detail::typelist<Event>;
67+
68+ adapted_event (const Event& event)
69+ : m_event{event}
70+ {
71+ }
72+
73+
74+ operator const Event&() const
75+ {
76+ return m_event;
77+ }
78+
79+ private:
80+ const Event& m_event;
81+ };
82+
83+
6084 // ! Holds the subscriber event type and the handler instance
6185 // ! in a type-erased manner so that they can be put into a
6286 // ! homogeneous container (e.g. the std::unordered_multimap as below)
@@ -98,9 +122,13 @@ namespace mpm
98122 template <typename E, typename H, typename Enable=void >
99123 struct model : concept
100124 {
101- explicit model (H h) : handler(std::move(h)) { }
125+ explicit model (H h)
126+ : handler(std::move(h))
127+ {
128+ }
129+
102130
103- void deliver (const detail:: event& e) override final
131+ void deliver (const event& e) override final
104132 {
105133 handler (static_cast <const E&>(e));
106134 }
@@ -110,21 +138,21 @@ namespace mpm
110138
111139
112140 // Specialization for events that do not use
113- // enable_polymorphic_dispatch. The diffence is that we must use
114- // *dynamic_cast* in this case as the dispatch_as event type (E)
115- // will not have detail::event as a base class
141+ // enable_polymorphic_dispatch. The diffence is that we static_cast
142+ // to adapted_event<E>.
116143 template <typename E, typename H>
117144 struct model <E, H, typename std::enable_if<
118145 !std::is_base_of<detail::event, E>::value>::type> : concept
119146 {
120- explicit model (H h) : handler(std::move(h)) { }
147+ explicit model (H h)
148+ : handler(std::move(h))
149+ {
150+ }
121151
122- void deliver (const detail::event& e) override final
152+
153+ void deliver (const event& e) override final
123154 {
124- if (const E* ptr = dynamic_cast <const E*>(&e))
125- {
126- handler (*ptr);
127- }
155+ handler (static_cast <const adapted_event<E>&>(e));
128156 }
129157
130158 H handler;
@@ -201,19 +229,6 @@ namespace mpm
201229 {
202230 }
203231 };
204-
205-
206- template <typename Base>
207- class adapted_event : public detail ::event, public Base
208- {
209- public:
210- using dispatch_as = detail::typelist<Base>;
211-
212- adapted_event (const Base& base)
213- : Base(base)
214- {
215- }
216- };
217232 }
218233
219234 // ! A small POD type representing a subscription
@@ -256,10 +271,7 @@ namespace mpm
256271 publish (const E& event) noexcept ;
257272
258273 template <typename E>
259- typename std::enable_if<
260- !std::is_base_of<detail::event, E>::value &&
261- std::is_class<E>::value &&
262- std::is_nothrow_copy_constructible<E>::value>::type
274+ typename std::enable_if<!std::is_base_of<detail::event, E>::value>::type
263275 publish (const E& event) noexcept ;
264276
265277# endif
@@ -323,19 +335,16 @@ namespace mpm
323335 using types = typename detail::dispatch_typelist<Event>::type;
324336 m_subscriptions.observe (
325337 [&](typename subscriptions::const_reference subs){
326- detail::for_each_type<types>(
327- detail::deliver<decltype (subs)>( event, subs) );
338+ detail::for_each_type<types>(
339+ detail::deliver<decltype (subs)>{ event, subs} );
328340 }
329341 );
330342 }
331343
332344
333345 template <typename A>
334346 template <typename Event>
335- typename std::enable_if<
336- !std::is_base_of<detail::event, Event>::value &&
337- std::is_class<Event>::value &&
338- std::is_nothrow_copy_constructible<Event>::value>::type
347+ typename std::enable_if<!std::is_base_of<detail::event, Event>::value>::type
339348 basic_eventbus<A>::publish(const Event& event) noexcept
340349 {
341350 publish (detail::adapted_event<Event>{event});
@@ -348,8 +357,8 @@ namespace mpm
348357 cookie
349358 basic_eventbus<A>::subscribe(const EventHandler& handler)
350359 {
351- static_assert (std::is_class <Event>::value,
352- " Events must be class types" );
360+ static_assert (std::is_object <Event>::value,
361+ " Events must be object types" );
353362 static_assert (noexcept (handler (std::declval<const Event&>())),
354363 " Need noexcept handler for Event" );
355364
0 commit comments