Originally intended to talk to you about how to operate in C + + Lua, after all, the main function of this frame is the implementation of LUA, but think maybe some friends do not know much about Lua, so before we talk about how to communicate with LUA, then you can first understand what Lua is a ghost, oh, yes, I use the 5.3 version, although this version has no third-party library, but now a lot of commonly used things I have already added good, so handy is also irrelevant.
So where do we start today? Well, well, just start with the "Properties" thing. Property this thing may not be the property that people think about, I take the name this thing has been a colleague spit trough 10 times, always feel my name inexplicably, okay, don't say these, First come to know what my so-called property is really a ghost.
Assuming that object a represents a rectangle, then he will have a concept of length and width, another object B represents an ellipse, and when object A's size changes, object B can know that the size of a changes and make corresponding changes, which is what I call the concept of properties, long and wide are the properties of a rectangle, The property changes will notify the object concerned about his property to do the corresponding action, and now I use the code to simulate this situation:
//===================================
Class a{
Public
void SetValue (const mstring& value) {
if (Mvalue = = value)
Return
Mvalue = value;
}
Private
Mstring Mvalue;
};
Class b{
Public
void SetValue (const mstring& value) {
if (Mvalue = = value)
Return
Mvalue = value;
}
Private
Mstring Mvalue;
};
void Testfun (const mstring& value) {
Errorbox ("Testfun called")
}
int main () {
A Obja;
B OBJB;
Obja.setvalue (123);
return 0;
}
//======================================
Now what we have to do is that when the Class A setvalue is called, the Class B SetValue is also invoked, that is, the value of a mvalue is modified, then B should also modify its own mvalue value, and now we have to solve the problem.
There may be a lot of ways to solve this problem, if in QT we can consider using the signal slot to solve, in MFC can consider using event notification to complete, in C # using event delegation to complete, well, but it seems that no matter which way of feeling is not the ideal, Because if the signal slot is used then we may have to define multiple signals if we need to observe multiple properties, and we also need to define a lot of event types if we use events, so these are not a once and for all methods, which is what I think is the most ideal method.
You may think of what we call the boost inside the signal slot, good idea, but this QT signal slot itself is almost something, so the same dissatisfaction, of course, the most important point, if we call SetValue through Obja will trigger OBJB SetValue, And OBJB will trigger the testfun when calling SetValue, then either the signal slots of the QT or the boost signal slots are not possible, so well, there seems to be no room for choice, either the function object or the function pointer.
The next thing to say may be my words can not be very good to say clearly, it is important that we understand the code, I think a yard win thousand words. For Obja and OBJB to be connected so inevitably through a medium, if this function is connect, then we will first set the following form:
Connect (SIGANL (obja,xxxx), SLOT (objb,xxxx));
This form mimics the QT Connect, so let's see if we can implement this connect function, and what should be his parameters? Think about it, when we operate Obja then OBJB will get corresponding response, So in this function we have to at least know that the Obja and OBJB are associated with that function, so it should be necessary to pass the function to Connnect. OK, now let's look at a prototype:
Template
void Connect (
Const mstring& Funname,
void (T::* fun1) (Args ...),
T* Obj1,
Std::function Eventfun
)
From this prototype we are almost certain that this is what we need, Funname is the function of the name FUN1 is obja to invoke the function, Obj1 is the function that we are triggered, from this function prototype to see that he is supporting infinite parameters, So what he's done is that the QT signal slot, or the boost signal, is not going to work, so what do you think it might be like? Of course more likely to be called this function? We can further encapsulate the same as above and then call it as follows:
Connect (Msignal (TestA, SetValue, &obja), Mslot (&B::SETVALUE,&OBJB));
Does that mean it's clear? Msignal Packaging is the name of the class, the function, the pointer to the object, the Mslot parameter is the address of the member function and the object pointer, OK, this as our calling convention, then the question comes, msignal and mslot How to implement it? Why are the two parameter calls so big? ? To satisfy the prototype of our connect above, signal must be able to generate a string with the same function name as the function pointer and an object pointer, and Mslot will generate a function object from the address of the member function and the object pointer.
Do you think it's starting to get a little confused? Well, we're going deeper on the C + + path, because these are almost certainly not used in the normal use process if they're not built for the purpose of building a library.
Msignal and Mslot are so much different because they are implemented in a way that is very easy, because the reality of msignal is quite simple, in fact, he is a macro definition:
#ifndef msignal
#define Msignal (classname,memfun,obj) #memFun, &classname::memfun,obj
#endif
But the implementation of Mslot is quite complex, it is not so easy to say clearly, the code, although not many, but want to settle is need to ponder:
//===================================
//
Here are just a few helper functions that don't need to be read, just know how to use Mslot
//
Template
struct mpropertyfunhelp{
Template
Static inline Auto Apply (T t,f fun,k obj, Args...args)
Decltype
Mpropertyfunhelp::apply
(
T,fun, obj,
Std::get (t),
Args ...)
)
{
Return mpropertyfunhelp::apply
(
T,fun,obj,
Std::get (t),
Args ...
);
}
};
Template<>
struct mpropertyfunhelp<0>{
Template
Static inline auto Apply (T T, F fun,k Obj,args...args)->decltype (
Std::bind (Fun,obj,args ...)
)
{
Return Std::bind (Fun,obj,args ...);
}
};
Template
struct tofun{
Template
Static Std::function Apply (T t,f fun,k obj) {
Auto __t = Std::tuple_cat (T,std::make_tuple (Std::_ph ()));
Return tofun::apply
(__t,fun,obj);
}
};
Template
struct tofun{
Template
Static Std::function Apply (T t,f fun,k obj) {
Return mpropertyfunhelp::apply (t,fun,obj);
}
};
//
Wrapper member function, we need to use the following function
//
Template
Std::function Mslot (R (T::* fun) (Args ...), t* obj) {
Auto T = std::make_tuple ();
Return tofun<0,sizeof ... (Args), r>::apply
(
T,fun,obj
);
}
//
Packing free function
//
Template
Std::function Mslot (R (*fun) (Args ...) {
Return std::forward> (fun);
}
//================================
The following function can be called correctly:
Connect (Msignal (TestA, SetValue, &obja), Mslot (&B::SETVALUE,&OBJB));
This invocation pattern is suitable for any type including free functions and is not constrained by the number of arguments is the same way of invocation, that is, regardless of the parameters of SetValue and SetValue the above function call is still unchanged.
C + + Tutorial Directx11frame properties