00001 //---------------------------------------------------------------------------- 00002 /** @file GoModBoard.h */ 00003 //---------------------------------------------------------------------------- 00004 00005 #ifndef GO_MODBOARD_H 00006 #define GO_MODBOARD_H 00007 00008 #include "GoAssertBoardRestored.h" 00009 00010 //---------------------------------------------------------------------------- 00011 00012 /** Make a const board temporarily modifiable. 00013 Allows functions to use a const board for performing temporary operations 00014 on the board (e.g. searches), as long as the board is in the same state 00015 after the function is finished. This class facilitates const-correctness 00016 and encapsulation, because it allows the owner of a board, which is the 00017 only one who is allowed to do persistent changes on the board, to hand out 00018 only a const reference to other code. The other code can still use the 00019 board for temporary operations without needing a copy of the board. 00020 GoModBoard does a const_cast from the const reference to a non-const 00021 reference in its constructor and checks with GoAssertBoardRestored in its 00022 destructor that the board is returned in the same state. 00023 00024 Example: 00025 @code 00026 // myFunction is not supposed to do persistent changes on the board 00027 // and therefore gets a const-reference. However it wants to use 00028 // the board temporarily 00029 void myFunction(const GoBoard& constBoard) 00030 { 00031 GoModBoard modBoard(constBoard); 00032 GoBoard& bd = modBoard.Board(); // get a nonconst-reference 00033 00034 // ... play some moves and undo them 00035 00036 // end of lifetime for modBoard, GoAssertBoardRestored is 00037 // automatically called in the destructor of modBoard 00038 } 00039 @endcode 00040 00041 There are also functions that allow to lock and unlock the board 00042 explicitly, for cases in which the period of temporary modifications 00043 cannot be mapped to the lifetime of a GoModBoard instance (e.g. because 00044 the period starts end ends in different functions). 00045 */ 00046 class GoModBoard 00047 { 00048 public: 00049 /** Constructor. 00050 Remembers the current board state. 00051 @param bd The board 00052 @param locked Whether to start in locked mode (for explicit usage 00053 of Lock() and Unlock()) 00054 */ 00055 GoModBoard(const GoBoard& bd, bool locked = false); 00056 00057 /** Destructor. 00058 Checks with assertions that the board state is restored. 00059 */ 00060 ~GoModBoard(); 00061 00062 /** Explicit conversion to non-const reference. 00063 This function triggers an assertion, if the board is currently in 00064 locked mode. 00065 */ 00066 GoBoard& Board() const; 00067 00068 /** Automatic conversion to non-const reference. 00069 Allows to pass GoModBoard to functions that expect a non-const GoBoard 00070 reference without explicitely calling GoModBoard.Board(). 00071 @see Board() 00072 */ 00073 operator GoBoard&() const; 00074 00075 /** Explicitely unlock the board. */ 00076 void Unlock(); 00077 00078 /** Explicitely lock the board. 00079 Checks with assertions that the board state is restored. 00080 See Lock() 00081 */ 00082 void Lock(); 00083 00084 private: 00085 bool m_locked; 00086 00087 GoBoard& m_bd; 00088 00089 GoAssertBoardRestored m_assertRestored; 00090 }; 00091 00092 inline GoModBoard::GoModBoard(const GoBoard& bd, bool locked) 00093 : m_locked(locked), 00094 m_bd(const_cast<GoBoard&>(bd)), 00095 m_assertRestored(bd) 00096 { 00097 } 00098 00099 inline GoModBoard::~GoModBoard() 00100 { 00101 // Destructor of m_assertRestored calls AssertRestored() 00102 } 00103 00104 inline GoModBoard::operator GoBoard&() const 00105 { 00106 return Board(); 00107 } 00108 00109 inline GoBoard& GoModBoard::Board() const 00110 { 00111 SG_ASSERT(! m_locked); 00112 return m_bd; 00113 } 00114 00115 inline void GoModBoard::Unlock() 00116 { 00117 m_assertRestored.Init(m_bd); 00118 m_locked = false; 00119 } 00120 00121 inline void GoModBoard::Lock() 00122 { 00123 m_assertRestored.AssertRestored(); 00124 m_assertRestored.Clear(); 00125 m_locked = true; 00126 } 00127 00128 //---------------------------------------------------------------------------- 00129 00130 #endif // GO_MODBOARD_H