The Code
I have a templated type that follows the Observer Pattern.
template <typename T>
class Subject {
public:
template <template<typename> typename Observer>
void AddObserver(Observer<T>& observer)
{
observers.push_back([&](const T& value) { observer.OnEvent(value); });
}
void Event(const T& value) const
{
for (auto& o : observers) {
o.OnEvent(value)
}
}
private:
std::vector<std::function<void(const T&)>> observers;
};
The above works great but only so long as the Observer
is a templated type. So I can modify the template signature and accept any type, regardless of whether they are templated.
template <typename Observer>
void AddObserver(Observer& observer)
{
observers.push_back([&](const T& value) { observer.OnEvent(value); });
}
The Issue
But now there aren't any compile time checks on type matching between the Subject and the Observer. (EDIT it has been pointed out that there is no guarantee that Observer<T>
actually uses T
in its OnEvent
function signature)
I'd like to add a static cast to the function that checks that the two types Subject<**T**>
and the Observer::OnEvent(const **T**&)
are the same, to prevent automagic type conversions. Something like the below.
static_cast(std::is_same<T, **type_of_first_param**(Observer::OnEvent)>::value, "Subject/Observer type mistatch.");
Possible approach that I need help with
If I cannot extract the type from the function signature, perhaps I can construct a function signature to which I can compare it?
static_cast(std::is_same<**Observer::MadeUpFunc(const T&)**, Observer::OnEvent>::value, "Subject/Observer type mistatch.");
I'm investigating this QA, and I'm pretty sure it holds the answer I need, just need some time and perhaps guidance to figure it out.
I have tried the following, but get the compile time error
typename specifier refers to non-type member 'OnEvent' in 'Observer'
static_assert(std::is_same<typename Observer::OnEvent, void (Observer::*)(const T&...)>::value, "");
What I have tried
- I have read the documentation here cppreference.com/w/cpp/types
- I have read some of the documentation here cppreference.com/w/cpp/language, namely the sections under Functions and Templates
- I have read this drdobbs.com/cpp/extracting-function-parameter-and-return
- I have looked at these similar QAs Extracting function argument types as a parameter pack, “unpacking” a tuple to call a matching function pointer