-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Proposal for observers and deferred implementations (#1599)
- Loading branch information
Showing
6 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#ifndef __IMPLEMENTATION_H__ | ||
#define __IMPLEMENTATION_H__ | ||
|
||
#include <functional> | ||
#include <optional> | ||
|
||
/** | ||
* @brief A way to defer the implementation of an action. | ||
* | ||
* @tparam R The result of the action. | ||
* @tparam T The types of the arguments that the implementation requires. | ||
*/ | ||
template <typename R, typename... T> | ||
class Implementation { | ||
public: | ||
typedef std::function<std::optional<R>(T...)> ImplementationFunction; | ||
|
||
/** | ||
* @brief Sets the implementation of the action. | ||
* | ||
* @param implementation The implementation of the action. | ||
*/ | ||
void SetImplementation(const ImplementationFunction& implementation) { | ||
this->implementation = implementation; | ||
} | ||
|
||
/** | ||
* @brief Clears the implementation of the action. | ||
*/ | ||
void ClearImplementation() { | ||
implementation.reset(); | ||
} | ||
|
||
/** | ||
* @brief Checks if the implementation is set. | ||
* | ||
* @return true If the implementation is set. | ||
* @return false If the implementation is not set. | ||
*/ | ||
bool IsSet() const { | ||
return implementation.has_value(); | ||
} | ||
|
||
/** | ||
* @brief Executes the implementation if it is set. | ||
* | ||
* @param args The arguments to pass to the implementation. | ||
* @return std::optional<R> The optional result of the implementation. If the result is not set, it indicates that the default action should be taken. | ||
*/ | ||
std::optional<R> Execute(T... args) const { | ||
return IsSet() ? implementation.value()(args...) : std::nullopt; | ||
} | ||
|
||
/** | ||
* @brief Exectues the implementation if it is set, otherwise returns a default value. | ||
* | ||
* @param args The arguments to pass to the implementation. | ||
* @param defaultValue The default value to return if the implementation is not set or should not be deferred. | ||
*/ | ||
R ExecuteWithDefault(T... args, const R& defaultValue) const { | ||
return Execute(args...).value_or(defaultValue); | ||
} | ||
|
||
/** | ||
* = operator overload. | ||
*/ | ||
Implementation& operator=(const Implementation& other) { | ||
implementation = other.implementation; | ||
return *this; | ||
} | ||
|
||
/** | ||
* = operator overload. | ||
*/ | ||
Implementation& operator=(const ImplementationFunction& implementation) { | ||
this->implementation = implementation; | ||
return *this; | ||
} | ||
|
||
/** | ||
* () operator overload. | ||
*/ | ||
std::optional<R> operator()(T... args) { | ||
return !IsSet() ? std::nullopt : implementation(args...); | ||
} | ||
|
||
private: | ||
std::optional<ImplementationFunction> implementation; | ||
|
||
}; | ||
|
||
#endif //!__IMPLEMENTATION_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#ifndef __OBSERVABLE_H__ | ||
#define __OBSERVABLE_H__ | ||
|
||
#include <vector> | ||
#include <functional> | ||
|
||
/** | ||
* @brief An event which can be observed by multiple observers. | ||
* | ||
* @tparam T The types of the arguments to be passed to the observers. | ||
*/ | ||
template <typename... T> | ||
class Observable { | ||
public: | ||
typedef std::function<void(T...)> Observer; | ||
|
||
/** | ||
* @brief Adds an observer to the event. | ||
* | ||
* @param observer The observer to add. | ||
*/ | ||
void AddObserver(const Observer& observer) { | ||
observers.push_back(observer); | ||
} | ||
|
||
/** | ||
* @brief Removes an observer from the event. | ||
* | ||
* @param observer The observer to remove. | ||
*/ | ||
void RemoveObserver(const Observer& observer) { | ||
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end()); | ||
} | ||
|
||
/** | ||
* @brief Notifies all observers of the event. | ||
* | ||
* @param args The arguments to pass to the observers. | ||
*/ | ||
void Notify(T... args) { | ||
for (const auto& observer : observers) { | ||
observer(args...); | ||
} | ||
} | ||
|
||
/** | ||
* += operator overload. | ||
*/ | ||
Observable& operator+=(const Observer& observer) { | ||
AddObserver(observer); | ||
return *this; | ||
} | ||
|
||
/** | ||
* -= operator overload. | ||
*/ | ||
Observable& operator-=(const Observer& observer) { | ||
RemoveObserver(observer); | ||
return *this; | ||
} | ||
|
||
/** | ||
* () operator overload. | ||
*/ | ||
void operator()(T... args) { | ||
Notify(args...); | ||
} | ||
|
||
private: | ||
std::vector<Observer> observers; | ||
}; | ||
|
||
#endif //!__OBSERVABLE_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters