Callback

Comparison of Callback and Template

    A. First Edition

    This is only a simple demo of comparison of "callback" and template implementation.

    B.The problem

Suppose you need write a general method for other users, allowing the user to use its self-defined method in

your method, how to implement it?

The typical answer is "callback" function. Besides it, you can use a template class. Here I just want to demo

how to do it.

    这个小例子是我们都玩过的剪刀石头布。有一个裁判程序（judge)，你和我都有一个出手的程序(youFight, meFight)和以及各自的策略数据(yourStrategy,

    myStrategy)。使用的时候就把他们都当作参数带入裁判程序。

    为什么要这样写呢？原因就是flexibility，假如，你忽然想要改变策略数据的话，就换一个参数带入就好了，裁判时不用变得。你也可以改变你的出牌的方法

    也就是重新定义一个新函数，只要参数类型个数，返回值类型与现在的一样就可以了，比如说，改变shift的值，或者就干脆用随机数等等。

C.The idea of program
The program is like a little game which we all played in childhood: "scissors-stone-cloth". The game is cycle-
win: scissors>cloth>stone>scissors.
Now you are asked to write a "judge" program which take two player's parameters. The parameter includes their
strategy of how to play the game, or more probably along with their data of strategy, say an array of playing
strategy. Your "judge" program call the parameters and get the choices from each of two players and judge the
the winner, show the winning information. That's it.
The first approach is by "callback" function which passes function pointer as parameter, along with their
strategy array. It is most common one.
The second approach is to pass a user-defined class which has "static" method and data. When the static method
is called, they will extract static strategy from its private data member and give the choice. It is more
completely wrapped method. However, there is a big bug of VC++6.0 as the compiler doesn't recognize the template
function from its declaration. This is a same annoying bug I encountered when overloading friend function of
"ostream".

    D.The major functions

    E.Further improvement

    F.File listing

    1. callback.cpp

    2. template.cpp

    CallBack Method:

    file name: callback.cpp

    #include <iostream>

    using namespace std;

    //this is not a program, but a joke...hahha...
    const int MatchNumber=10;

    //you know what they are, right?
    //we all play this little game
    enum FightType
    {Scissor, Stone, Cloth};

    char* typeStr[3]={"Scissor", "Stone", "Cloth"};

    //this is the sequence you might play
    int yourStrategy[MatchNumber]={2,1,0,2,1,2,0,2,1,1};
    //this is the sequence I might play
    int myStrategy[MatchNumber]={0,1,2,1,2,1,0,2,1,0};

    //this is the match judge, with two your play function and your strategy
    //and my function and my strategy
    void judge(int (* youPlay)(int* yourParam, int theNumber), int* yourParam,
    			 int (*myPlay)(int* myParam, int theNumber), int* myParam);

    //actually this is the function you defined here
    int youFight(int* youParam, int index);
    //I won't repeat
    int meFight(int* myParam, int index);

    int main()
    {
    	judge(youFight, yourStrategy, meFight, myStrategy);
    	return 0;
    }

    void judge(int (* youPlay)(int* theParam, int index), int* yourParam,
    			 int (*myPlay)(int* theParam, int index), int* myParam)
    {
    	int you, me;
    	for (int i=0; i<MatchNumber; i++)
    	{
    		you=youPlay(yourParam, i);
    		me=myPlay(myParam, i);
    		cout<<"your type is:"<<typeStr[you]<<endl;
    		cout<<"my type is:"<<typeStr[me]<<endl;
    		switch (you-me)
    		{

    		case 0:

    			cout<<"it is a tie on match no."<<i+1<<endl;
    			break;
    		case 1:
    		case -2:
    			cout<<"you win on match no. "<<i+1<<endl;
    			break;
    		case -1:
    		case 2:
    			cout<<"you lose on match no."<<i+1<<endl;
    			break;
    		}
    	}
    }

    //you can change your strategy simple by....
    int youFight(int* youParam, int index)
    {
    	//actually you can define any method you imagine
    	return yourStrategy[(index+5)%MatchNumber];
    }

    int meFight(int* myParam, int index)
    {
    	//by shifting the current strategy, you have a new one
    	return myStrategy[(index+2)%MatchNumber];
    }

    Template Method:

    The result of callback method:

    your type is:Cloth
    my type is:Cloth
    it is a tie on match no.1
    your type is:Scissor
    my type is:Stone
    you lose on match no.2
    your type is:Cloth
    my type is:Cloth
    it is a tie on match no.3
    your type is:Stone
    my type is:Stone
    it is a tie on match no.4
    your type is:Stone
    my type is:Scissor
    you win on match no. 5
    your type is:Cloth
    my type is:Cloth
    it is a tie on match no.6
    your type is:Stone
    my type is:Stone
    it is a tie on match no.7
    your type is:Scissor
    my type is:Scissor
    it is a tie on match no.8
    your type is:Cloth
    my type is:Scissor
    you lose on match no.9
    your type is:Stone
    my type is:Stone
    it is a tie on match no.10
    Press any key to continue

    file name: rules.cpp

    #include <iostream>

    using namespace std;

    //this is not a program, but a joke...hahha...
    const int MatchNumber=10;

    //you know what they are, right?
    //we all play this little game
    enum FightType
    {Scissor, Stone, Cloth};

    char* typeStr[3]={"Scissor", "Stone", "Cloth"};

    class YourPlay
    {
    private:
    	static int yourStrategy[MatchNumber];
    public:
    	static int youFight(int index)
    	{
    		//actually you can define any method you imagine
    		return yourStrategy[(index+5)%MatchNumber];
    	}
    };

    class MyPlay
    {
    private:
    	static int myStrategy[MatchNumber];
    public:
    	static int meFight(int index)
    	{
    		//by shifting the current strategy, you have a new one
    		return myStrategy[(index+2)%MatchNumber];
    	}
    };

    //the static strategy is initialized here
    int YourPlay::yourStrategy[MatchNumber]={2,1,0,2,1,2,0,2,1,1};
    int MyPlay::myStrategy[MatchNumber]={0,1,2,1,2,1,0,2,1,0};

    //THIS IS THE BUG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //you cannot declare the template function
    //compiler don't recognize it!!!
    //believe it or not, try declare it as following:
    /*
    template<class yourPlayClass , class myPlayClass>
    void judge();
    */
    //and put the implementation below after "MAIN" function
    //then you will get memory access error, because
    //what you declared is not implemented!!!!!
    template<class yourPlayClass , class myPlayClass>
    void judge()
    {
    	int you, me;
    	for (int i=0; i<MatchNumber; i++)
    	{
    		you=yourPlayClass::youFight(i);
    		me=myPlayClass::meFight(i);
    		cout<<"your type is:"<<typeStr[you]<<endl;
    		cout<<"my type is:"<<typeStr[me]<<endl;
    		switch (you-me)
    		{

    		case 0:

    			cout<<"it is a tie on match no."<<i+1<<endl;
    			break;
    		case 1:
    		case -2:
    			cout<<"you win on match no. "<<i+1<<endl;
    			break;
    		case -1:
    		case 2:
    			cout<<"you lose on match no."<<i+1<<endl;
    			break;
    		}
    	}
    }

    int main()
    {
    	judge<YourPlay, MyPlay>();
    	return 0;
    }

    The result of callback method:

    your type is:Cloth
    my type is:Cloth
    it is a tie on match no.1
    your type is:Scissor
    my type is:Stone
    you lose on match no.2
    your type is:Cloth
    my type is:Cloth
    it is a tie on match no.3
    your type is:Stone
    my type is:Stone
    it is a tie on match no.4
    your type is:Stone
    my type is:Scissor
    you win on match no. 5
    your type is:Cloth
    my type is:Cloth
    it is a tie on match no.6
    your type is:Stone
    my type is:Stone
    it is a tie on match no.7
    your type is:Scissor
    my type is:Scissor
    it is a tie on match no.8
    your type is:Cloth
    my type is:Scissor
    you lose on match no.9
    your type is:Stone
    my type is:Stone
    it is a tie on match no.10
    Press any key to continue