Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

template non-type template parameters

Following is my code to register a free function or member function as callback.

Find code here https://cppinsights.io/s/58dcf235

#include <stdio.h>
#include <iostream>
#include <functional>
#include <vector>
using namespace std;

class IEvent
{
    
public:
    int m_EventType;
    virtual ~IEvent() {}
};

template<class...Args>
class Event : public IEvent {};

template<int eventType,class...Args>
class Event<int eventType, bool(Args...)> : public IEvent
{
public:
    Event(bool(*func)(Args...)) :m_FnPtr(func)
    { 
         m_EventType = eventType;
         m_ListenersList.push_back(m_FnPtr);
    }

    template <typename T>
    Event(T* obj, bool(T::* Func)(Args...))
    {
        m_EventType = eventType;
        m_FnPtr = [obj, Func](Args&&... args)->bool {
            return (obj->*Func)(std::forward<Args>(args)...);
        };
        
        m_ListenersList.push_back(m_FnPtr);
    }

    void NotifyListeners(Args&&...args) const
    {
        for (auto& itr : m_ListenersList)
        {
            (itr)(std::forward<Args>(args)...);
        }
        
    }
private:
    std::function<bool(Args...)> m_FnPtr;
    std::vector<std::function<bool(Args...)>> m_ListenersList; 
};

class Window
{
public:
    bool OnKeyUp(bool, double)
    {
        cout << endl << "Member Function called";
        return true;
    }

    bool OnClicked()
    {
        cout << endl << "OnClicked";
        return true;
    }
    
    //using KeyupListenerType = Event<"KeyUp", bool(bool, double)>;
};

int main()
{
    Window w;
    Event<90,bool(bool, double)> evnt(&w, &Window::OnKeyUp);
    //Event<100,bool()> evnt(&w, &Window::OnClicked);
    evnt.NotifyListeners(true, 6.8);
    return 0;
}

But I’m getting errors at line:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Event<90,bool(bool, double)> evnt(&w, &Window::OnKeyUp);

I’m trying to assign an event type to the event listener as shown below.
I want to assign the event type during instantiation itself. But I get the following errors

26 | class Event<int, bool(Args...)> : public IEvent
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:26:7: note:         ‘eventType’
main.cpp: In function ‘int main()’:
main.cpp:80:32: error: type/value mismatch at argument 1 in template parameter list for ‘template class Event’
   80 |     Event<90,bool(bool, double)> evnt(&w, &Window::OnKeyUp);
      |                                ^
main.cpp:80:32: note:   expected a type, got ‘90’
main.cpp:80:62: error: expression list treated as compound expression in initializer [-fpermissive]
   80 |     Event<90,bool(bool, double)> evnt(&w, &Window::OnKeyUp);
      |                                                              ^
main.cpp:80:62: error: cannot convert ‘bool (Window::*)(bool, double)’ to ‘int’ in initialization
main.cpp:81:10: error: request for member ‘NotifyListeners’ in ‘evnt’, which is of non-class type ‘int’
   81 |     evnt.NotifyListeners(true, 6.8);
      |          ^~~~~~~~~~~~~~~

What mistake I’m doing? How to pass non-type parameters?

>Solution :

Your base declaration does not match your specialization.

The base implementation has template <class...Args> while the specialzation wants template <int eventType, class...Args>.

You also put an extra int that does not belong there in the declaration for the specialization here:

template<int eventType,class...Args>
class Event<int eventType, bool(Args...)> : public IEvent
            ^^^ here

The adjusted code would look like this

#include <stdio.h>
#include <iostream>
#include <functional>
#include <vector>
using namespace std;

class IEvent
{
    
public:
    int m_EventType;
    virtual ~IEvent() {}
};

template<int eventType, class...Args>
class Event : public IEvent {};

template<int eventType,class...Args>
class Event<eventType, bool(Args...)> : public IEvent
{
public:
    Event(bool(*func)(Args...)) :m_FnPtr(func)
    { 
         m_EventType = eventType;
         m_ListenersList.push_back(m_FnPtr);
    }

    template <typename T>
    Event(T* obj, bool(T::* Func)(Args...))
    {
        m_EventType = eventType;
        m_FnPtr = [obj, Func](Args&&... args)->bool {
            return (obj->*Func)(std::forward<Args>(args)...);
        };
        
        m_ListenersList.push_back(m_FnPtr);
    }

    void NotifyListeners(Args&&...args) const
    {
        for (auto& itr : m_ListenersList)
        {
            (itr)(std::forward<Args>(args)...);
        }
        
    }
private:
    std::function<bool(Args...)> m_FnPtr;
    std::vector<std::function<bool(Args...)>> m_ListenersList; 
};

class Window
{
public:
    bool OnKeyUp(bool, double)
    {
        cout << endl << "Member Function called";
        return true;
    }

    bool OnClicked()
    {
        cout << endl << "OnClicked";
        return true;
    }
    
    //using KeyupListenerType = Event<"KeyUp", bool(bool, double)>;
};

int main()
{
    Window w;
    Event<90,bool(bool, double)> evnt(&w, &Window::OnKeyUp);
    //Event<100,bool()> evnt(&w, &Window::OnClicked);
    evnt.NotifyListeners(true, 6.8);
    return 0;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading