Implementation of a C ++ Delegate

xiaoxiao2021-03-06  44

Update Description: Modified the excuse, add support to Smart_PTR. Recently, a C Delegate implementation is needed, which is more close to the DELEGATE of C #. Turning over Boost, although there are similar things, it is always useful: Function: The binding method can be accepted, and the way member function call is not unhappy. Moreover, the same function prototype, Native and Member correspond to the Function type, and the MEMBER FUNCTION type of the same prototype of different classes is also different. Signal: It is good, however, a built-in SLOT device, is inconvenient to intervene interference, two, how to bind a general member function, do not know how to implement, only Native function and functor can be bound. Bind: It is what I want. Unfortunately, the placeholders are up to 3. There is also a Siglib library, I saw it yesterday, it is too late. Look at it, the method of calling, it seems to be dragging water. It is not that I like to invent the wheel, I really have to have already, I have to write Delegate yourself. The handwritten code is not long, and it is attached to the use of .deltegate. Note: DELEGATE usage and C # are similar, relatively simple. Really, the code is not complicated. Didn't consider the problem of portability.

two. use:

1. example

Delegate dele_binary;

Delegate a delegate: dele_binary, dele_binary can hold the following form:

INT NAVIVE_FUN (INT, INT);

Struct functor {

Int operator () (int, int);

} a_functor;

Struct a {

INT MEM_FUN (INT, INT);

} an_A;

Bind the process of delegate to the actual function:

Dele_binary.connect (& native_fun); // Bind to normal functions, & operators are optional

Dele_binary.connect (& a_functor); // Bind to the imitation function, & it must be

Dele_binary.connect (& A_A, & A :: Mem_fun); // Bind to the ordinary member function, two & all must

Note: Dele_binary type definition template parameters are: int, int, do not add *, which can refer to Boost :: function. This is a standard, and the disadvantage is that the transplantability is temporarily affected.

2. Call mode

Delegate is overloaded with Operator (), and has a unified call form for the above three binding procedures:

INT x = dele_binary (1, 2);

Delegate is overloaded with Operator (). At the same time, it can be noted that the difference in the example is only in the form of Connect, and the data type of Dele_binary is determined, so delegate can be placed in the container or there is no differential call. In addition, Delegate itself is also a function, or in another delegate, in general, it is recommended to avoid this.

For convenience, it is also allowed to directly connect to the delegated object in the constructor of Delegate, as follows: delegate dele_binary_fun;

Delegate dele_binary (& a_functor);

Delegate dele_binary (& AN_A, & A :: MEM_FUN);

Before calling the delegated object via the Delegate, you must make sure the Delegate instance is connected to an object. You can be checked by the Connected method, is connected to the determined object. You can also disconnect and object connections through Disconnect. Method The prototype is as follows:

Bool connect () const;

Void disconnect ();

3. COPY & ASSIGNMENT

Delegate has a deep copy semantics.

three. Implementation

The actual implementation uses considerable macros, not what I will. However, my usage is just to replace the simplest string of the simpler as the simpler, and there is no complicated skill, so the problem should be no problem, I don't want to have a lengthy discussion here. Welcome to discuss implementation, semantic issues. Code section: / * CopyWrite: Don't tease (non-typical bald) DESCRIPTION: C DELEGATE implementation. Can be copied, modified, distributed, and use. Don't say it is your own. ^ _ ^ * / # ifndef delegate_h # deflude "contract.h" Namespace nice {template Class Delegate;

#define DELEGATE (TEMPLATE_ARGS, FUNCTION_ARGS, FUNCTION_PARA) / template / class delegate / {/ struct FunctionHolder / {/ virtual Ret operator () (FUNCTION_ARGS) = 0; / virtual FunctionHolder * clone () const = 0; / virtual ~ FunctionHolder () {}; /}; / FunctionHolder * h; // template / struct FunctorHolder: public FunctionHolder / {/ FunctorPtr Fun; / FunctorHolder (FunctorPtr nfun): Fun (NFUN) {} / Virtual Ret Operator () (function_args) / {/ return (* fun) (Function_PARA); /} / Virtual FunctionHolder * Clone () const / {/ return new functorHolder (* this); /} / }; // template / Struct MemHolder: Public FunctionHolder / {/ U Obj; / Memfun Memfun; // MemHolder (U Aobj, Memfun AMFUN) /: OBJ (AOBJ), MEMFUN (AMFUN) { } // Virtual Ret Operator () (function_args) / {/ return ((* obj). * Memfun (function_para); /} / virtual functionHolder * Clone () const / {/ return New memholder (* this); /} /}; / functionHolder * CloneHolder () const / {/ if (connection ()) / return h-> clone (); / return null; /} / public: / delegate () : h (0) / {/} / ~ delegate () / {/ disconnect (); /} // Template / delegate (Functorptr NFUN_) /: h (New FunctorHolder (NFUN_)) / {/} // delegate (const delegate & r Hs): h (rhs.cloneholder ()) / {} / template / delegate (u Aobj, Memfun Mfun) /: h (New MemHolder (AOBJ, MFUN)) / {/} / delegate & operator = (const delegate & r HS) / {/ if (& rhs! = This) / {/ disconnect (); / h = rhs.cloneholder ();

/} / Return * this; /} / template / void connection _) / {/ disconnect (); / h = new functorHolder (nfun _); /} // Template / Void Connect (U Aobj, Memfun MFUN) / {/ if (h) delete h; / h = new memory (aobj, mfun); /} // void disconnect () / {/ IF (Connected ()) delete h; / h = 0; /} // Bool connection () const / {/ return (h! = null); /} // Ret Operator () (function_args) / {/ pre_condition connected ()); / return (* h) (FUNCTION_PARA); /} /}; // * / # define TEMPLATE_ARGS_0 #define FUNCTION_ARGS_0 # define FUNCTION_PARA_0 # define TEMPLATE_ARGS_1, typename T0 # define FUNCTION_ARGS_1 T0 t0 # define FUNCTION_PARA_1 t0

/ * Defines generate code: for (int i = 2; i <= 50; i ) {printf ("# define template_args_% d template_args_% d, Typename T% D / N", I, I - 1, i - 1 ); Printf ("# define function_args_% d function_args_% D, T% DT% D / N", I, I - 1, I - 1, I - 1); Printf ("# define function_para_% d function_para_% D, T% D / N / N ", I, I - 1, I - 1);

For (int i = 0; i <= 50; i) Printf ("DELEGATE_ARGS_% D, FUNCTION_ARGS_% D, FUNCTION_PARA_% D) / N", I, I, I); * / / / Auto Generate "---------------------------------------------- # Define TEMPLATE_ARGS_2 TEMPLATE_ARGS_1, typename T1 # define FUNCTION_ARGS_2 FUNCTION_ARGS_1, T1 t1 # define FUNCTION_PARA_2 FUNCTION_PARA_1, t1 .... # define TEMPLATE_ARGS_3 TEMPLATE_ARGS_2, typename T2 # define FUNCTION_ARGS_3 FUNCTION_ARGS_2, T2 t2 # define FUNCTION_PARA_3 FUNCTION_PARA_2, t2

#define TEMPLATE_ARGS_4 TEMPLATE_ARGS_3, typename T3 # define FUNCTION_ARGS_4 FUNCTION_ARGS_3, T3 t3 # define FUNCTION_PARA_4 FUNCTION_PARA_3, t3 ... DELEGATE (TEMPLATE_ARGS_0, FUNCTION_ARGS_0, FUNCTION_PARA_0) DELEGATE (TEMPLATE_ARGS_1, FUNCTION_ARGS_1, FUNCTION_PARA_1) DELEGATE (TEMPLATE_ARGS_2, FUNCTION_ARGS_2, FUNCTION_PARA_2) DELEGATE (TEMPLATE_ARGS_3 , Function_args_3, function_para_3) ...}; # ENDIF / / END DELEGATE_H Test case: cppunit_test_suite_registration (Test_Delegate); Using Namespace Nice;

INT local_add (int A, int b) {RETURN A B;}

Struct functor_add {INT M; INT MEM_ADD (INT A, INT B) {RETURN A B M;}}

Struct functor_mul {int m; int operator () (int A, int b) {RETURN (A B) * m;}}

Void test_dlegate :: testmain () {typedef delegate Testdele2;

// Default CTOR is not connected to Testdele2 dele1; cppunit_assert (! Dele1.connected ());

// connect testde2 dele2 (local_add); cppUnit_assert (dele2.connected ());

// Call CPPUNIT_ASSERT (Dele2 (2, 3) == 5);

// copy ctor testdele2 dele3 = dele2; cppunit_assert (dele3.connected ()); cppunit_assert (dele3 (2, 3) == 5);

// disconnect dele2.disconnect (); cppUnit_assert (! de2.connected ()); // Test Clone cppUnit_assert (dele3.connected ()); dele3 (2, 3); cppunit_assert (dele3 (2, 3) == 5 ); // assign dele2 = dele3; cppUnit_assert (dele2 (2, 3) == 5);

// MEMBER FUNCTION FUNCTOR_ADD Fctor; fctor.m = 7; Dele2.connect (& fctor, & functor_add :: MEM_ADD); CPPUNIT_ASSERT (dele2 (2, 3) == 12);

// functor functor_mul fm; fm.m = 3; testdele2 dele4 (& fm); cppunit_assert (dele4 (2, 3) == 15); fm.m = 4; cppUnit_assert (dele4 (2, 3) == 20);

转载请注明原文地址:https://www.9cbs.com/read-86937.html

New Post(0)