lldoubledispatch_tut.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file   lldoubledispatch_tut.cpp
  3.  * @author Nat Goodspeed
  4.  * @date   2008-11-13
  5.  * @brief  Test for lldoubledispatch.h
  6.  *
  7.  * This program tests the DoubleDispatch class, using a variation on the example
  8.  * from Scott Meyers' "More Effective C++", Item 31.
  9.  *
  10.  * $LicenseInfo:firstyear=2008&license=viewergpl$
  11.  * 
  12.  * Copyright (c) 2008-2010, Linden Research, Inc.
  13.  * 
  14.  * Second Life Viewer Source Code
  15.  * The source code in this file ("Source Code") is provided by Linden Lab
  16.  * to you under the terms of the GNU General Public License, version 2.0
  17.  * ("GPL"), unless you have obtained a separate licensing agreement
  18.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  19.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  20.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  21.  * 
  22.  * There are special exceptions to the terms and conditions of the GPL as
  23.  * it is applied to this Source Code. View the full text of the exception
  24.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  25.  * online at
  26.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  27.  * 
  28.  * By copying, modifying or distributing this software, you acknowledge
  29.  * that you have read and understood your obligations described above,
  30.  * and agree to abide by those obligations.
  31.  * 
  32.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  33.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  34.  * COMPLETENESS OR PERFORMANCE.
  35.  * $/LicenseInfo$
  36.  */
  37. // Precompiled header
  38. #include "linden_common.h"
  39. // associated header
  40. #include "lldoubledispatch.h"
  41. // STL headers
  42. // std headers
  43. #include <string>
  44. #include <iostream>
  45. #include <typeinfo>
  46. // external library headers
  47. // other Linden headers
  48. #include "lltut.h"
  49. /*---------------------------- Class hierarchy -----------------------------*/
  50. // All objects are GameObjects.
  51. class GameObject
  52. {
  53. public:
  54.     GameObject(const std::string& name): mName(name) {}
  55.     virtual ~GameObject() {}
  56.     virtual std::string stringize() { return std::string(typeid(*this).name()) + " " + mName; }
  57. protected:
  58.     std::string mName;
  59. };
  60. // SpaceStation, Asteroid and SpaceShip are peer GameObjects.
  61. struct SpaceStation: public GameObject
  62. {
  63.     SpaceStation(const std::string& name): GameObject(name) {}
  64.     // Only a dummy SpaceStation is constructed without a name
  65.     SpaceStation(): GameObject("dummy") {}
  66. };
  67. struct Asteroid: public GameObject
  68. {
  69.     Asteroid(const std::string& name): GameObject(name) {}
  70.     Asteroid(): GameObject("dummy") {}
  71. };
  72. struct SpaceShip: public GameObject
  73. {
  74.     SpaceShip(const std::string& name): GameObject(name) {}
  75.     SpaceShip(): GameObject("dummy") {}
  76. };
  77. // SpaceShip is specialized further into CommercialShip and MilitaryShip.
  78. struct CommercialShip: public SpaceShip
  79. {
  80.     CommercialShip(const std::string& name): SpaceShip(name) {}
  81.     CommercialShip(): SpaceShip("dummy") {}
  82. };
  83. struct MilitaryShip: public SpaceShip
  84. {
  85.     MilitaryShip(const std::string& name): SpaceShip(name) {}
  86.     MilitaryShip(): SpaceShip("dummy") {}
  87. };
  88. /*-------------------------- Collision functions ---------------------------*/
  89. // This mechanism permits us to overcome a limitation of Meyers' approach:  we
  90. // can declare the parameter types exactly as we want, rather than having to
  91. // make them all GameObject& parameters.
  92. std::string shipAsteroid(SpaceShip& ship, Asteroid& rock)
  93. {
  94. //  std::cout << rock.stringize() << " has pulverized " << ship.stringize() << std::endl;
  95.     return "shipAsteroid";
  96. }
  97. std::string militaryShipAsteroid(MilitaryShip& ship, Asteroid& rock)
  98. {
  99. //  std::cout << rock.stringize() << " has severely damaged " << ship.stringize() << std::endl;
  100.     return "militaryShipAsteroid";
  101. }
  102. std::string shipStation(SpaceShip& ship, SpaceStation& dock)
  103. {
  104. //  std::cout << ship.stringize() << " has docked at " << dock.stringize() << std::endl;
  105.     return "shipStation";
  106. }
  107. std::string asteroidStation(Asteroid& rock, SpaceStation& dock)
  108. {
  109. //  std::cout << rock.stringize() << " has damaged " << dock.stringize() << std::endl;
  110.     return "asteroidStation";
  111. }
  112. /*------------------------------- Test code --------------------------------*/
  113. namespace tut
  114. {
  115.     struct dispatch_data
  116.     {
  117.         dispatch_data():
  118.             home(new SpaceStation("Terra Station")),
  119.             obstacle(new Asteroid("Ganymede")),
  120.             tug(new CommercialShip("Pilotfish")),
  121.             patrol(new MilitaryShip("Enterprise"))
  122.         {}
  123.         // Instantiate and populate the DoubleDispatch object.
  124.         typedef LLDoubleDispatch<std::string, GameObject> DD;
  125.         DD dispatcher;
  126.         // Instantiate a few GameObjects.  Make sure we refer to them
  127.         // polymorphically, and don't let them leak.
  128.         std::auto_ptr<GameObject> home;
  129.         std::auto_ptr<GameObject> obstacle;
  130.         std::auto_ptr<GameObject> tug;
  131.         std::auto_ptr<GameObject> patrol;
  132.         // prototype objects
  133.         Asteroid dummyAsteroid;
  134.         SpaceShip dummyShip;
  135.         MilitaryShip dummyMilitary;
  136.         CommercialShip dummyCommercial;
  137.         SpaceStation dummyStation;
  138.     };
  139.     typedef test_group<dispatch_data> dispatch_group;
  140.     typedef dispatch_group::object dispatch_object;
  141.     tut::dispatch_group ddgr("double dispatch");
  142.     template<> template<>
  143.     void dispatch_object::test<1>()
  144.     {
  145.         // Describe param types using explicit DD::Type objects
  146.         // (order-sensitive add() variant)
  147.         dispatcher.add(DD::Type<SpaceShip>(), DD::Type<Asteroid>(), shipAsteroid, true);
  148.         // naive adding, won't work
  149.         dispatcher.add(DD::Type<MilitaryShip>(), DD::Type<Asteroid>(), militaryShipAsteroid, true);
  150.         dispatcher.add(DD::Type<SpaceShip>(), DD::Type<SpaceStation>(), shipStation, true);
  151.         dispatcher.add(DD::Type<Asteroid>(), DD::Type<SpaceStation>(), asteroidStation, true);
  152.         // Try colliding them.
  153.         ensure_equals(dispatcher(*home, *tug),        // reverse params, SpaceShip subclass
  154.                       "shipStation");
  155.         ensure_equals(dispatcher(*patrol, *home),     // forward params, SpaceShip subclass
  156.                       "shipStation");
  157.         ensure_equals(dispatcher(*obstacle, *home),   // forward params
  158.                       "asteroidStation");
  159.         ensure_equals(dispatcher(*home, *obstacle),   // reverse params
  160.                       "asteroidStation");
  161.         ensure_equals(dispatcher(*tug, *obstacle),    // forward params, SpaceShip subclass
  162.                       "shipAsteroid");
  163.         ensure_equals(dispatcher(*obstacle, *patrol), // reverse params, SpaceShip subclass
  164.                       // won't use militaryShipAsteroid() because it was added
  165.                       // in wrong order
  166.                       "shipAsteroid");
  167.     }
  168.     template<> template<>
  169.     void dispatch_object::test<2>()
  170.     {
  171.         // Describe param types using explicit DD::Type objects
  172.         // (order-sensitive add() variant)
  173.         // adding in correct order
  174.         dispatcher.add(DD::Type<MilitaryShip>(), DD::Type<Asteroid>(), militaryShipAsteroid, true);
  175.         dispatcher.add(DD::Type<SpaceShip>(), DD::Type<Asteroid>(), shipAsteroid, true);
  176.         dispatcher.add(DD::Type<SpaceShip>(), DD::Type<SpaceStation>(), shipStation, true);
  177.         dispatcher.add(DD::Type<Asteroid>(), DD::Type<SpaceStation>(), asteroidStation, true);
  178.         
  179.         ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
  180.         ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
  181.     }
  182.     template<> template<>
  183.     void dispatch_object::test<3>()
  184.     {
  185.         // Describe param types with actual prototype instances
  186.         // (order-insensitive add() variant)
  187.         dispatcher.add(dummyMilitary, dummyAsteroid, militaryShipAsteroid);
  188.         dispatcher.add(dummyShip, dummyAsteroid, shipAsteroid);
  189.         dispatcher.add(dummyShip, dummyStation, shipStation);
  190.         dispatcher.add(dummyAsteroid, dummyStation, asteroidStation);
  191.         ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
  192.         ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
  193.         ensure_equals(dispatcher(*obstacle, *patrol), "");
  194.     }
  195.     template<> template<>
  196.     void dispatch_object::test<4>()
  197.     {
  198.         // Describe param types with actual prototype instances
  199.         // (order-insensitive add() variant)
  200.         dispatcher.add(dummyShip, dummyAsteroid, shipAsteroid);
  201.         // Even if we add the militaryShipAsteroid in the wrong order, it
  202.         // should still work.
  203.         dispatcher.add(dummyMilitary, dummyAsteroid, militaryShipAsteroid);
  204.         dispatcher.add(dummyShip, dummyStation, shipStation);
  205.         dispatcher.add(dummyAsteroid, dummyStation, asteroidStation);
  206.         ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
  207.         ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
  208.     }
  209.     template<> template<>
  210.     void dispatch_object::test<5>()
  211.     {
  212.         dispatcher.add<SpaceShip, Asteroid>(shipAsteroid);
  213.         dispatcher.add<MilitaryShip, Asteroid>(militaryShipAsteroid);
  214.         dispatcher.add<SpaceShip, SpaceStation>(shipStation);
  215.         dispatcher.add<Asteroid, SpaceStation>(asteroidStation);
  216.         ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
  217.         ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
  218.     }
  219. } // namespace tut