I have an instance of a class A which should register a member callback in another instance of class B. I'm trying to keep the reference to the function of class A inside class B but I get a Segfault.
classA.h:
std::shared_ptr<classB> mB;
void toBeRegisteredCallback(const uint8_t val);
classA.cpp:
classA::classA(std::shared_ptr<classB> b) :
mB(std::move(b)) {
b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this,
std::placeholders::_1));
}
void classB::toBeRegisteredCallback(const uint8_t val) {
LOG(INFO) << "Received a value callback!";
}
Here is the code for classB.h:
public:
void registerCallback(std::function<void(const uint8_t val)> callback);
private:
std::function<void(const uint8_t)> _callback;
Here is code for classB.cpp:
void classB::registerCallback(std::function<void(const uint8_t val)> callback) {
_callback = callback;
}
When I try to call the callback directly without assignment, it works fine:
callback(8)
However, if I try to assign it, I get a segfault at functionswap
Thanks.
Consider your classA constructor...
classA::classA(std::shared_ptr<classB> b)
: mB(std::move(b))
{
b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this,
std::placeholders::_1));
}
The initialization of mB will invoke (from here(item 10))...
shared_ptr( shared_ptr&& r ) noexcept;
Move-constructs a shared_ptr from r. After the construction, *this
contains a copy of the previous state of r, r is empty and its
stored pointer is null.
Hence, in the following statement...
b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this, std::placeholders::_1));
b is effectively a null pointer resulting in undefined behaviour.
I am not quite sure what you want to do, but I created a working example below.
You may give me feedback if that helps you, or if you need more explanation.
(As already mentioned by john you should be careful with the std::move command)
#include <memory>
#include <functional>
#include <iostream>
class classB
{
public:
classB() {}
~classB() {}
public:
void registerCallback(std::function<void(const uint8_t val)> callback)
{
_callback = callback;
}
void callCallback()
{
if(_callback)
_callback(8);
}
private:
std::function<void(const uint8_t)> _callback;
};
class classA
{
public:
classA(std::shared_ptr<classB> b)
: mB(b)
{
b->registerCallback(std::bind(&classA::toBeRegisteredCallback, this, std::placeholders::_1));
}
~classA(){}
void toBeRegisteredCallback(const uint8_t /*val*/)
{
std::cout << "Received a value callback!" << std::endl;
}
private:
std::shared_ptr<classB> mB;
};
int main(int, char *[])
{
std::shared_ptr<classB> b = std::make_shared<classB>();
classA localClassA = classA(b);
b->callCallback();
system("pause");
}
Related
I am using C++ 14 with clang on MacOS Sierra. I want to enforce a rule by design. Following is the rule.
I have a member variable in my class say:
unsigned int m_important_num;
There are 4 methods in my class.
fun1();
fun2();
fun3();
fun4();
Objective:
I want only fun2() to be able to change the value of m_important_num.
Question:
Is it possible to make it compiler error if any method other than fun2() changes the variable?
One possible way is to declare it const somehow empower fun2() to change const variables? Is this a good solution? Or are their any better solutions?
Secondary question:
Is it a wrong design to try do such a thing?
Sort of, with additional layer:
class S1 {
public:
void fun2() { /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
unsigned int m_important_num;
};
class S2 : private S1
{
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
As Yakk commented, if func2 need access to S2 members, CRTP can solve that:
template <typename Derived>
class S1 {
public:
void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
unsigned int m_important_num;
};
class S2 : private S1<S2>
{
// friend class S1<S2>; // If required.
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
Encapsulate it down. Put m_important_num in its own class. Aggregate it in your existing class. Have a getter for it. Then put fun2() as a member function of your inner class.
I little variant (if I understand correctly) of the Jeffrey solution: put the variable in an inner class and make it private; create a public getter and make func2() friend to the inner class.
I mean
struct foo
{
int f1 () { return b0.getVal(); }; // you can read `val` everywhere
void f2 () { b0.val = 42; }; // you can write `val` in f2()
void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()
class bar
{
private:
int val = 24;
public:
int getVal () { return val; }
friend void foo::f2 ();
};
bar b0;
};
In other words: friend is your friend.
If you want to prevent a method from modifying any member in the class you can use the trailing const identifier:
class something{
private:
unsigned int var;
public:
void fun1() const;
void fun2();
void fun3() const;
void fun4() const;
}
Here, only fun2() will be able to modify the variable.
I know there are lots of good answers, but there is also an option that you sort of alluded to in your question:
One possible way is to declare it const somehow empower fun2() to change const variables?
#include <iostream>
using uint = unsigned int;
class Test
{
const uint num;
public:
Test(uint _num)
:
num(_num)
{}
uint get_num() const
{
return num;
}
void can_change_num(uint _new_num)
{
uint& n(const_cast<uint&>(num));
n = _new_num;
}
void cant_change_num(uint _new_num)
{
// num = _new_num; // Doesn't compile
}
};
int main()
{
Test t(1);
std::cout << "Num is " << t.get_num() << "\n";
t.can_change_num(10);
std::cout << "Num is " << t.get_num() << "\n";
return 0;
}
Produces
Num is 1
Num is 10
You already got lots of good answers to your primary question. I'll try to address the secondary one.
Is it a wrong design to try do such a thing?
It's hard to say w/o knowing more about your design. In general anything like this detected during a code review would raise a big red flag. Such a protection makes sense in a case of a big class with convoluted logic/implementation. Otherwise why would you like to go an extra mile and make your code much more complicated? The fact you seek for this can indicate your class became unmanageable.
I'd recommend to consider splitting it to smaller parts with better defined logic where you won't worry such mistakes can happen easily.
I have a FreeRTOS function xTaskCreate. Simplified declaration looks like
typedef void (*TaskFunction_t)( void* );
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void*params );
And there are two classes:
class Super {
virtual void task(void*params) = 0;
};
class Derived1 : public Super {
virtual void task(void*params){ while(1){ blinkLed(1); delay_ms(333); } }
};
class Derived2 : public Super { ... ;}
In function init() I select one of derived classes and create its instance. Then want to create task
void init(){
Super *obj = condition ? new Derived1 : new Derived2;
xTaskCreate( obj->task ); // WRONG.
}
Upd. Add missed void*params in Simplified declaration of xTaskCreate.
TaskFunction_t is just a pointer to a function - so it can't take a pointer to a member function. Only a pointer to normal function. Or a static member function. Or a lambda with no capture. It's that last one that we'll take advantage of.
One of the arguments you removed from your simplified declaration is the context:
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
unsigned short usStackDepth,
void *pvParameters, // <== this one!
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
);
You provide the Super* in the parameters and provide a lambda that knows what to do with it. Altogether:
void init(){
Super *obj = condition ? new Derived1 : new Derived2;
xTaskCreate([](void* o){ static_cast<Super*>(o)->task(); },
..., // other args here
obj,
... // more args
);
}
Note that task() should take no arguments. The void*is the context that we're converting to a Super*.
After several experiements of my own with answers here I prefered this simpler method giving Object oriented function calls to RTOS tasks.
//These are not full declaration of class IModule which is fully abstarct so //object that are IModule* are always inherited.
protected:
virtual int InitModule() = 0;
virtual bool PreLoop() = 0;
virtual bool DoLoop() = 0;
virtual bool PostLoop() = 0;
virtual bool DoShutdown() = 0;
//Return if this module implementation requires an RTOS task looping.
virtual bool isFreeRTOSTaskRequired() = 0;
private:
TaskHandle_t *moduleLoopTaskHandle;
bool CreateRTOSTask();
static void TaskStart(void* taskStartParameters);
void TaskLoop();
//END OF PARTIAL decleration
bool IModule::CreateRTOSTask()
{
xTaskCreate(IModule::TaskStart, "NAME", 2048, this, tskNO_AFFINITY, moduleLoopTaskHandle);
return true;
}
void IModule::TaskStart(void *taskStartParameters)
{
IModule *moduleObject = (IModule *)taskStartParameters;
moduleObject->TaskLoop();
}
void IModule::TaskLoop()
{
//TODO Buraya ölçüm koyalım ve bir değişkene yazalım
while (true)
{
ESP_LOGD("IModule::TaskLoop", "%s", "I am alive!");
if (!PreLoop())
{
}
if (!DoLoop())
{
}
if (!PostLoop())
{
}
}
vTaskDelete(NULL);
}
UPDATED: See below.
As explained better than I can here, you might get away with this. Hard to tell from your question if it will cover all of your requirements.
typedef void (Super::*TaskFunction_t)( void* );
Further Reading
UPDATE:
I fleshed out your example, and the results and code are below:
XXXXX:~/scratch/member_function_pointer$ bin/provemeright
Condition false
virtual void Derived2::task(void*)
XXXXX:~/scratch/member_function_pointer$ bin/provemeright foo
Condition true because of argument foo
virtual void Derived1::task(void*)
code (all one cpp file, bad form, but proves syntax):
#include <iostream>
class Super;
typedef void (Super::*TaskFunction_t)(void*);
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void* params);
bool condition = false;
class Super {
public: virtual void task(void* params) = 0;
};
class Derived1 : public Super {
public: virtual void task(void* params) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if(params) // Necessary to prevent unused parameter warning
std::cout << "Not Null" << std::endl;
};
};
class Derived2 : public Super {
public: virtual void task(void* params) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if(params) // Necessary to prevent unused parameter warning
std::cout << "Not Null" << std::endl;
};
};
void init(){
Super *obj = condition ? (Super*)new Derived1 : (Super*)new Derived2;
xTaskCreate( &Super::task , obj);
}
int main(int argc, char **argv)
{
if(argc > 1)
{
std::cout << "Condition true because of argument " << argv[1] << std::endl;
condition = true;
} else {
std::cout << "Condition false" << std::endl;
}
init();
return 0;
}
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void* params)
{
Super *obj = (Super*) params;
(obj->*pxTaskCode)(NULL);
return 0;
}
If you're concerned that the syntax is &Super::task instead of &obj->task, then you're misunderstanding how virtual functions work. (It turns out that the &obj->task syntax forbidden by ISO C++, but gcc says it's permissive, so you shouldn't but could force it to compile, and get exactly the same result)
The information about which virtual version of a function to call 'lives' in the object, not the type system. (Could probably phrase that better, open to suggestions, but I think it gets the general point across) It is impossible to call a member function without an object, so in order to make use of the function pointer, you'll have to have an object to 'call it on'. It is the type of that object which will determine which virtual function gets called. So the code above should achieve whatever you're going for, unless of course, this is a round-about way to determine the type of the object pointed to by obj, in which case, it's an awfully convoluted way of going about it.
Further Reading specifically in "Kerrek SB"s answer.
Here is some code:
typedef void (*ACallBack)(int i);
class SomeClass
{
private:
ACallBack aCallBack;
public:
void SetCallBack(ACallBack aCallBack);
};
void SomeClass::SetCallBack(ACallBack aCallBack)
{
this->aCallBack = aCallBack;
}
class SomeOtherClass
{
private:
SomeClass someClass;
public:
void InitializeSomeClass();
private:
void callBackMethod(int i);
};
void SomeOtherClass::InitializeSomeClass()
{
this->changeVariable = 10;
this->someClass.SetCallBack(this->callBackMethod); // DOESN'T WORK
this->someClass.UseCallBack();
}
void SomeOtherClass::callBackMethod(int i)
{
}
void globalCallBack(int i)
{
int myInt = i;
}
int main()
{
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
}
Basically if I try to set my callback function in SomeOtherClass it doesn't work but when I set it globally in main it does. What am I missing here?
Just use std::function and std::bind():
typedef std::function<void(int i)> ACallBack;
// old code pretty much the same
int main()
{
using namespace std::placeholders;
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
SomeOtherClass oC;
sC.SetCallBack(std::bind(&SomeOtherClass::callBackMethod,oC,_1)); //WORKS AS WELL!!
}
In this case you do not really need to pass void *userData but may add it as well if you need old code to compile.
You have to make the method static:
static void callBackMethod(int i, void* userData);
if you need a pointer to a method that is not static, ie an instance method, it becomes more complex.
typedef void ( myclass::*FUNC ) (int i, void* userData);
and if you want to use it, it becomes a hastlle :
myclass obj; // instantiate myclass
FUNC f = &myclass::myfunc; // assign address
( obj.*f ) ( 123, NULL ); // and call it
I have the following situation, (better in code)
class Foo
{
private:
typedef boost::signal<void ()> Signal;
Signal signal;
public:
void Register_SignalFunction(const Signal::slot_type& slot);
void Unregister_SignalFunction(const Signal::slog_type& slot);
}
class OtherFoo
{
Foo foo;
public:
OtherFoo()
{
foo.Register_SignalFunction(&OnSignal) //I know I can't do this that is precisely my question.
}
void OnSignal(); //what to do when signal fires
}
So the question is, how i pass a 'member-function' pointer to the Register method. Also, is this ok? What I want/need, is some sort of delegate registration system, so if anynone could point my in the right direction I'll appreciate it. Thanx in advance.
You would typically use boost bind:
foo.Register_SignalFunction(boost::bind(&OtherFoo::OnSignal, this));
What's going on here? :-)
The connect method of the signal takes a functor. That is an object that implements the () operator. bind takes function pointers (either to free functions or member functions) and returns a functor with the right signature.
Also see here:
Complete example using Boost::Signals for C++ Eventing
and here:
how boost::function and boost::bind work
To disconnect a signal store the return value from connect into a:
boost::signals::connection
And then call the disconnect method on that.
Typically you'll either do:
void Register_SignalFunction(const boost::function<void()> &slot) {
signal += slot;
}
Or, as an inline function:
template<typename T>
void Register_SignalFunction(T &slot) {
signal += slot;
}
The latter may be slightly more efficient by removing the layer of indirection boost::function has - but only assuming boost::signal doesn't use boost::function internally (which it is likely to). So use whichever one you prefer, really.
I got it working after trying a lot, here's the code:
GraphicsDeviceManager
{
private:
typedef boost::signal<void ()> DeviceLost;
DeviceLost deviceLost;
public:
Register_DeviceLostHandler(const boost::function<void ()> &handler)
{
deviceLost.connect(slot);
}
Unregister_DeviceLostHandler(const boost::function<void ()> &handler)
{
//deviceLost.disconnect(slot);
}
}
class GameBase
{
private:
GraphicsDeviceManager* graphics;
public:
GameBase()
{
graphics = new GraphicsDeviceManager();
graphics->Register_DeviceLostHandler(boost::bind(&GameBase::OnDeviceLost, this));
}
void OnDeviceLost()
{
//do some stuff
}
}
well this code works as it should be, with one exception, if I unccomment the deviceLost.disconnect(handler) statement, I receive compilation errors like:
error C266 "boost::operator ==": 4 overloads have similar conversions.
So, why is this happening? Do you know any other way to accomplish what I'm trying?
In case anyone wants a full example:
#include <iostream>
#include <boost/signals2/signal.hpp>
#include <boost/bind.hpp>
#include <boost/optional/optional_io.hpp>
#define registerEvent_(A) registerEvent(boost::bind(A, this, _1, _2))
struct A
{
typedef boost::signals2::signal<int (int &, int &)> EventSignal;
typedef EventSignal::slot_type SlotType;
void registerEvent(const SlotType & slot);
void triggerAll(int& a1, int& a2);
EventSignal signal_;
};
void A::registerEvent(const SlotType & slot) { signal_.connect(slot); }
void A::triggerAll(int& a1, int& a2) {std::cout << signal_(a1, a2) << "\n";}
struct B : public A
{
B();
int myFunc(int& a1, int& a2);
};
B::B() {
#ifdef WITHMACRO
registerEvent_(&B::myFunc);
#else
registerEvent(boost::bind(&B::myFunc, this, _1, _2));
#endif
}
int B::myFunc(int& a1, int& a2) { return a1 + a2 + 1; }
int main()
{
int a1 = 2;
int a2 = 3;
B b;
b.triggerAll(a1, a2);
}
Since I love progamming in both C# and C++, I'm about to implementing a C#-like event system as a solid base for my planned C++ SFML-GUI.
This is only an excerpt of my code and I hope this clarifies my concept:
// Event.h
// STL headers:
#include <functional>
#include <type_traits>
#include <iostream>
// boost headers:
#include <boost/signals/trackable.hpp>
#include <boost/signal.hpp>
namespace Utils
{
namespace Gui
{
#define IMPLEMENTS_EVENT(EVENTNAME, EVENTARGS) public: \
Utils::Gui::IEvent<EVENTARGS>& EVENTNAME() { return m_on##EVENTNAME; } \
protected: \
virtual void On##EVENTNAME(EVENTARGS& e) { m_on##EVENTNAME(this, e); } \
private: \
Utils::Gui::Event<EVENTARGS> m_on##EVENTNAME;
#define MAKE_EVENTFIRING_CLASS(EVENTNAME, EVENTARGS) class Fires##EVENTNAME##Event \
{ \
IMPLEMENTS_EVENT(EVENTNAME, EVENTARGS); \
};
class EventArgs
{
public:
static EventArgs Empty;
};
EventArgs EventArgs::Empty = EventArgs();
template<class TEventArgs>
class EventHandler : public std::function<void (void*, TEventArgs&)>
{
static_assert(std::is_base_of<EventArgs, TEventArgs>::value,
"EventHandler must be instantiated with a TEventArgs template paramater type deriving from EventArgs.");
public:
typedef void Signature(void*, TEventArgs&);
typedef void (*HandlerPtr)(void*, TEventArgs&);
EventHandler() : std::function<Signature>() { }
template<class TContravariantEventArgs>
EventHandler(const EventHandler<TContravariantEventArgs>& rhs)
: std::function<Signature>(reinterpret_cast<HandlerPtr>(*rhs.target<EventHandler<TContravariantEventArgs>::HandlerPtr>()))
{
static_assert(std::is_base_of<TContravariantEventArgs, TEventArgs>::value,
"The eventHandler instance to copy does not suffice the rules of contravariance.");
}
template<class F>
EventHandler(F f) : std::function<Signature>(f) { }
template<class F, class Allocator>
EventHandler(F f, Allocator alloc) : std::function<Signature>(f, alloc) { }
};
template<class TEventArgs>
class IEvent
{
public:
typedef boost::signal<void (void*, TEventArgs&)> SignalType;
void operator+= (const EventHandler<TEventArgs>& eventHandler)
{
Subscribe(eventHandler);
}
void operator-= (const EventHandler<TEventArgs>& eventHandler)
{
Unsubscribe(eventHandler);
}
virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler) = 0;
virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler, int group) = 0;
virtual void Unsubscribe(const EventHandler<TEventArgs>& eventHandler) = 0;
};
template<class TEventArgs>
class Event : public IEvent<TEventArgs>
{
public:
virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler)
{
m_signal.connect(*eventHandler.target<EventHandler<TEventArgs>::HandlerPtr>());
}
virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler, int group)
{
m_signal.connect(group, *eventHandler.target<EventHandler<TEventArgs>::HandlerPtr>());
}
virtual void Unsubscribe(const EventHandler<TEventArgs>& eventHandler)
{
m_signal.disconnect(*eventHandler.target<EventHandler<TEventArgs>::HandlerPtr>());
}
void operator() (void* sender, TEventArgs& e)
{
m_signal(sender, e);
}
private:
SignalType m_signal;
};
class IEventListener : public boost::signals::trackable
{
};
};
};
As you can see, I'm using boost::signal as my actual event system, but I encapsulate it with the IEvent interface (which is actually an abstract class) to prevent event listeners to fire the event via operator().
For convenience I overloaded the add-assignment and subtract-assignment operators. If I do now derive my event listening classes from IEventListener, I am able to write code without needing to worry about dangling function pointer in the signal.
So far I'm testing my results, but I have trouble with std::tr1::function::target<TFuncPtr>():
class BaseEventArgs : public Utils::Gui::EventArgs
{
};
class DerivedEventArgs : public BaseEventArgs
{
};
void Event_BaseEventRaised(void* sender, BaseEventArgs& e)
{
std::cout << "Event_BaseEventRaised called";
}
void Event_DerivedEventRaised(void* sender, DerivedEventArgs& e)
{
std::cout << "Event_DerivedEventRaised called";
}
int main()
{
using namespace Utils::Gui;
typedef EventHandler<BaseEventArgs>::HandlerPtr pfnBaseEventHandler;
typedef EventHandler<DerivedEventArgs>::HandlerPtr pfnNewEventHandler;
// BaseEventHandler with a function taking a BaseEventArgs
EventHandler<BaseEventArgs> baseEventHandler(Event_BaseEventRaised);
// DerivedEventHandler with a function taking a DerivedEventArgs
EventHandler<DerivedEventArgs> newEventHandler(Event_DerivedEventRaised);
// DerivedEventHandler with a function taking a BaseEventArgs -> Covariance
EventHandler<DerivedEventArgs> covariantBaseEventHandler(Event_BaseEventRaised);
const pfnBaseEventHandler* pBaseFunc = baseEventHandler.target<pfnBaseEventHandler>();
std::cout << "baseEventHandler function pointer is " << ((pBaseFunc != nullptr) ? "valid" : "invalid") << std::endl;
const pfnNewEventHandler* pNewFunc = newEventHandler.target<pfnNewEventHandler>();
std::cout << "baseEventHandler function pointer is " << ((pNewFunc != nullptr) ? "valid" : "invalid") << std::endl;
// Here is the error, covariantBaseEventHandler actually stores a pfnBaseEventHandler:
pNewFunc = covariantBaseEventHandler.target<pfnNewEventHandler>();
std::cout << "covariantBaseEventHandler as pfnNewEventHandler function pointer is " << ((pNewFunc != nullptr) ? "valid" : "invalid") << std::endl;
// This works as expected, but template forces compile-time knowledge of the function pointer type
pBaseFunc = covariantBaseEventHandler.target<pfnBaseEventHandler>();
std::cout << "covariantBaseEventHandler as pfnBaseEventHandler function pointer is " << ((pBaseFunc != nullptr) ? "valid" : "invalid") << std::endl;
return EXIT_SUCCESS;
}
The EventHandler<TEventArgs>::target<TFuncPtr>() method will only return a valid pointer if TFuncPtr is the exact same type as stored in the Functor, regardless of covariance.
Because of the RTTI check, it prohibits to access the pointer as a standard weakly-typed C function pointer, which is kind of annoying in cases like this one.
The EventHandler is of type DerivedEventArgs but nevertheless points to a pfnBaseEventHandler function even though the function ran through the constructor.
That means, that std::tr1::function itself "supports" contravariance, but I can't find a way of simply getting the function pointer out of the std::tr1::funcion object if I don't know its type at compile time which is required for a template argument.
I would appreciate in cases like this that they added a simple get() method like they did for RAII pointer types.
Since I'm quite new to programming, I would like to know if there is a way to solve this problem, preferrably at compile-time via templates (which I think would be the only way).
Just found a solution for the problem. It seems that I just missed a cast at a different location:
template<class TEventArgs>
class EventHandler : public std::function<void (void*, TEventArgs&)>
{
public:
typedef void Signature(void*, TEventArgs&);
typedef void (*HandlerPtr)(void*, TEventArgs&);
// ...
template<class TContravariantEventArgs>
EventHandler(const EventHandler<TContravariantEventArgs>& rhs)
: std::function<Signature>(reinterpret_cast<HandlerPtr>(*rhs.target<EventHandler<TContravariantEventArgs>::HandlerPtr>()))
{
static_assert(std::is_base_of<TContravariantEventArgs, TEventArgs>::value,
"The eventHandler instance to copy does not suffice the rules of contravariance.");
}
// ...
}
This works how it is supposed to work. Thank you nonetheless for giving me a smooth introduction into this really awesome community!