jontitorr / EventEmitter

A strictly-typed, event emitter implementation written in C++ 20.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to bind a method from a class instance

AleCaste opened this issue · comments

Hello, nice library!
I am getting compile errors when trying to use the "on" method with a method from a class instance.
Something like this:

class Person {
private:
  std::string name;
  int age;
public:
  Person(const std::string &p_name) : name(p_name) {}
  ~Person() {}
  void introduce() {
    std::cout << "Hi I'm a Person and my name is " << this->name << std::endl;
  }
  void setAge(const int &age) {
    this->age = age;
    std::cout << "Hi I'm " << this->name << " and I'm " << this->age << std::endl;
  }  
};

int main(int argc, char *argv[]) {
  
  EventEmitter e;
  Person p = Person("Peter");
  e.on("member1", std::bind(&Person::introduce, p)); 
  e.emit("member1");
}

The above throws the following errors:

cl.exe /std:c++20 /Zi /EHsc /nologo /FeC:\projects\event_emitter\main_neat.exe C:\projects\event_emitter\main_neat.cpp
main_neat.cpp
C:\projects\event_emitter\EventEmitterNeat\function_traits.hpp(10): error C3556: 'std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>::operator ()': incorrect argument to 'decltype'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(57): note: see reference to class template instantiation 'function_traits<std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>>' being compiled
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(58): note: see reference to alias template instantiation 'arg_types_t<std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>>' being compiled
C:\projects\event_emitter\main_neat.cpp(67): note: see reference to function template instantiation 'void EventEmitter::on<std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>>(std::string_view,Event)' being compiled
        with
        [
            Event=std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>
        ]
C:\projects\event_emitter\EventEmitterNeat\function_traits.hpp(10): error C3770: 'unknown-type': is not a valid base class
C:\projects\event_emitter\EventEmitterNeat\function_traits.hpp(38): error C2794: 'arg_types': is not a member of any direct or indirect base class of 'function_traits<std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>>'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(57): error C2938: 'arg_types_t' : Failed to specialize alias template
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(58): error C2672: 'make_unique': no matching overloaded function found
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\memory(3475): note: could be 'void std::make_unique(_Types &&...)'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(58): note: 'std::make_unique': invalid template argument for '_Ty', missing template argument list on class template 'EventListener'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\memory(3469): note: or       'std::unique_ptr<_Ty,std::default_delete<_Ty>> std::make_unique(const size_t)'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(58): note: 'std::make_unique': invalid template argument for '_Ty', missing template argument list on class template 'EventListener'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\memory(3464): note: or       'std::unique_ptr<_Ty,std::default_delete<_Ty>> std::make_unique(_Types &&...)'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(58): note: 'std::make_unique': invalid template argument for '_Ty', missing template argument list on class template 'EventListener'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(57): error C3536: 'listener': cannot be used before it is initialized
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): error C2665: 'std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back': no overloaded function could convert all the argument types
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\vector(874): note: could be 'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(_Ty &&)'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: 'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(_Ty &&)': cannot convert argument 1 from 'int' to '_Ty &&'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: Reason: cannot convert from 'int' to '_Ty'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: No constructor could take the source type, or constructor overload resolution was ambiguous
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\vector(870): note: or       'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(const _Ty &)'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: 'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(const _Ty &)': cannot convert argument 1 from 'int' to 'const _Ty &'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: Reason: cannot convert from 'int' to 'const _Ty'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: No constructor could take the source type, or constructor overload resolution was ambiguous
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(61): note: while trying to match the argument list '(int)'
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): error C2665: 'std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back': no overloaded function could convert all the argument types
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\vector(874): note: could be 'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(_Ty &&)'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: 'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(_Ty &&)': cannot convert argument 1 from 'int' to '_Ty &&'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: Reason: cannot convert from 'int' to '_Ty'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: No constructor could take the source type, or constructor overload resolution was ambiguous
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\include\vector(870): note: or       'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(const _Ty &)'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: 'void std::vector<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>,std::allocator<std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>>>::push_back(const _Ty &)': cannot convert argument 1 from 'int' to 'const _Ty &'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: Reason: cannot convert from 'int' to 'const _Ty'
        with
        [
            _Ty=std::unique_ptr<BaseEventListener,std::default_delete<BaseEventListener>>
        ]
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: No constructor could take the source type, or constructor overload resolution was ambiguous
C:\projects\event_emitter\EventEmitterNeat/EventEmitter.hpp(64): note: while trying to match the argument list '(int)'

Build finished with error(s).

This is the line the compiler complains about in function_traits.hpp

struct function_traits
    : public function_traits<decltype(&T::operator())> {      //  error C3556: 'std::_Binder<std::_Unforced,void (__thiscall Person::* )(void),Person &>::operator ()': incorrect argument to 'decltype'
};

It would be nice if the EventEmitter could call functions from class instances.
Is there a way this could be achieved?
Also, it'd be neat if the EventListener class would have an id that could be used to remove it from the list of listeners (through an "off" method). But that I can do, it's only a suggestion in case you want to add that functionality.

Again, great little lib!