diff --git a/include/etl/observer.h b/include/etl/observer.h index 3e915a59..133f8392 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -57,6 +57,7 @@ SOFTWARE. #include "exception.h" #include "error_handler.h" #include "utility.h" +#include "type_list.h" namespace etl { @@ -338,6 +339,19 @@ namespace etl virtual void notification() = 0; }; + //***************************************************************** + /// The observer class for N types. + /// Configured from a type list. + ///\ingroup observer + //***************************************************************** + template + class observer> : public observer + { + public: + + using observer::notification; + }; + #else //********************************************************************* diff --git a/test/test_observer.cpp b/test/test_observer.cpp index bf08e17b..5ae52139 100644 --- a/test/test_observer.cpp +++ b/test/test_observer.cpp @@ -68,12 +68,24 @@ namespace // The Notification2 is passed by reference. // The Notification3 is passed by const reference. //***************************************************************************** - typedef etl::observer ObserverType; + using ObserverType = etl::observer; + +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) + //***************************************************************************** + // The observer base type. + // Declare what notifications you want to observe and how they are passed to 'notification'. + // The Notification1 is passed by value. + // The Notification2 is passed by reference. + // The Notification3 is passed by const reference. + //***************************************************************************** + using NotificationList = etl::type_list; + using ObserverTypeFromTypeList = etl::observer; +#endif //***************************************************************************** // The observer base type that does not take a notification type. //***************************************************************************** - typedef etl::observer ObserverVoidIntType; + using ObserverVoidIntType = etl::observer; } //***************************************************************************** @@ -115,6 +127,29 @@ public: } }; +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) +//***************************************************************************** +// The concrete observable 3 class. +//***************************************************************************** +class Observable3 : public etl::observable +{ +public: + + Notification1 data1; + Notification2 data2; + Notification1& data3 = data1; + + //********************************* + // Notify all of the observers. + //********************************* + void send_notifications() + { + notify_observers(data3); + notify_observers(data2); + } +}; +#endif + //***************************************************************************** // The concrete observable 3 class. //***************************************************************************** @@ -229,6 +264,53 @@ public: int data3_count; }; +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) +//***************************************************************************** +// The third observer type. +// If any one of the overloads is missing or a parameter declaration is incorrect +// then the class will be 'abstract' and will not compile. +//***************************************************************************** +class Observer3 : public ObserverTypeFromTypeList +{ +public: + + Observer3() + : data1_count(0) + , data2_count(0) + , data3_count(0) + { + } + + //******************************************* + // Notification1 is passed by value. + //******************************************* + void notification(Notification1 /*data1*/) + { + ++data1_count; + } + + //******************************************* + // Notification2 is passed by reference. + //******************************************* + void notification(Notification2& /*data2*/) + { + ++data2_count; + } + + //******************************************* + // Notification3 is passed by const reference. + //******************************************* + void notification(const Notification3& /*data3*/) + { + ++data3_count; + } + + int data1_count; + int data2_count; + int data3_count; +}; +#endif + //***************************************************************************** // The third observer type. // If any one of the overloads is missing or a parameter declaration is incorrect @@ -399,6 +481,27 @@ namespace CHECK_EQUAL(3, observer2.data1_count); } +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) + //************************************************************************* + TEST(test_observer_created_from_a_type_list) + { + // The observable objects. + Observable3 observable3; + + // The observer objects. + Observer3 observer3; + + observable3.add_observer(observer3); + + // Send the notifications. + observable3.send_notifications(); // Updates data1 & data2. + + CHECK_EQUAL(1, observer3.data1_count); + CHECK_EQUAL(1, observer3.data2_count); + CHECK_EQUAL(0, observer3.data3_count); + } +#endif + //************************************************************************* TEST(test_8_notifications) {