fork download
  1. #include <iostream>
  2. #include <array>
  3. #include <vector>
  4. #include <cassert>
  5.  
  6. enum Direction {
  7. North, East, West, South
  8. };
  9. enum { NumDirections = static_cast<int>(South + 1) };
  10.  
  11. constexpr Direction reciprocalDirection(Direction dir)
  12. {
  13. // North :- 3 - 0 = 3 -> South
  14. // East :- 3 - 1 = 2 -> West
  15. // West :- 3 - 2 = 1 -> East
  16. // South :- 3 - 3 = 0 -> North
  17. return static_cast<Direction>(
  18. (NumDirections - 1) - static_cast<unsigned int>(dir)
  19. );
  20. }
  21.  
  22. struct Link
  23. {
  24. struct Room* m_room; // struct needed to forward-declare
  25. Link* m_reciprocal; // The link back to us.
  26.  
  27. Link() : m_room(nullptr), m_reciprocal(nullptr) {}
  28.  
  29. operator bool() const { return m_room != nullptr; }
  30.  
  31. static void Binder(Room* lhsRoom_, Link* lhsLink_, Link* rhsLink_, Room* rhsRoom_)
  32. {
  33. lhsLink_->m_room = rhsRoom_;
  34. lhsLink_->m_reciprocal = rhsLink_;
  35. rhsLink_->m_reciprocal = lhsLink_;
  36. rhsLink_->m_room = lhsRoom_;
  37. }
  38.  
  39. void unbind()
  40. {
  41. if (m_room) {
  42. m_room = m_reciprocal->m_room = nullptr;
  43. m_reciprocal->m_reciprocal = nullptr;
  44. m_reciprocal = nullptr;
  45. }
  46. }
  47.  
  48. ~Link() { unbind(); }
  49. };
  50.  
  51. struct Room
  52. {
  53. using Links = std::array<Link, NumDirections>;
  54.  
  55. template<typename T>
  56. Room(T&& name_) : m_name(std::forward<T>(name_))
  57. {
  58. std::cout << "Created Room(" << m_name << ") @ " << (void*)this << "\n";
  59. }
  60.  
  61. //! Indicates that from this room, in direction dir_, is room_
  62. void link(Direction dir_, Room* room_);
  63.  
  64. ~Room();
  65.  
  66. const Room* link(Direction dir_) const { return m_links[dir_].m_room; }
  67. Room* link(Direction dir_) { return m_links[dir_].m_room; }
  68.  
  69. const std::string& name() const { return m_name; }
  70.  
  71. private:
  72. std::string m_name;
  73. Links m_links;
  74. };
  75.  
  76. std::ostream& operator<<(std::ostream& os, const Room& rm)
  77. {
  78. os << "Room(" << rm.name() << ") @ " << (void*)(&rm);
  79. return os;
  80. }
  81.  
  82. int main()
  83. {
  84. Room* firstRoom = new Room("lobby");
  85.  
  86. Room* newRoom = new Room("office");
  87. firstRoom->link(North, newRoom);
  88.  
  89. firstRoom->link(South, new Room("bedroom"));
  90. firstRoom->link(West, new Room("bathroom"));
  91.  
  92. newRoom->link(East, new Room("closet"));
  93.  
  94. delete firstRoom;
  95. }
  96.  
  97. void Room::link(Direction dir_, Room* room_)
  98. {
  99. Direction opposite = reciprocalDirection(dir_);
  100. std::cout << "Linking " << *room_ << " to " << *this
  101. << " " << dir_ << ":" << opposite << "\n";
  102. Link::Binder(this, &m_links[dir_], &room_->m_links[opposite], room_);
  103. }
  104.  
  105. Room::~Room()
  106. {
  107. static size_t depth = 0;
  108. ++depth;
  109.  
  110. std::string indent(depth, '|');
  111.  
  112. std::cout << indent << "~" << *this << "\n";
  113.  
  114. std::vector<Room*> unlinked;
  115. for (auto& link: m_links) {
  116. if (link) {
  117. if (link.m_room != this)
  118. unlinked.push_back(link.m_room);
  119. std::cout << indent << "Unlinked " << *link.m_room << " from " << *this << "\n";
  120. link.unbind();
  121. }
  122. }
  123.  
  124. for (Room* room : unlinked) {
  125. delete room;
  126. }
  127.  
  128. --depth;
  129. }
  130.  
Success #stdin #stdout 0s 3276KB
stdin
Standard input is empty
stdout
Created Room(lobby) @ 0x9730008
Created Room(office) @ 0x9730048
Linking Room(office) @ 0x9730048 to Room(lobby) @ 0x9730008 0:3
Created Room(bedroom) @ 0x9730088
Linking Room(bedroom) @ 0x9730088 to Room(lobby) @ 0x9730008 3:0
Created Room(bathroom) @ 0x97300c8
Linking Room(bathroom) @ 0x97300c8 to Room(lobby) @ 0x9730008 2:1
Created Room(closet) @ 0x9730110
Linking Room(closet) @ 0x9730110 to Room(office) @ 0x9730048 1:2
|~Room(lobby) @ 0x9730008
|Unlinked Room(office) @ 0x9730048 from Room(lobby) @ 0x9730008
|Unlinked Room(bathroom) @ 0x97300c8 from Room(lobby) @ 0x9730008
|Unlinked Room(bedroom) @ 0x9730088 from Room(lobby) @ 0x9730008
||~Room(office) @ 0x9730048
||Unlinked Room(closet) @ 0x9730110 from Room(office) @ 0x9730048
|||~Room(closet) @ 0x9730110
||~Room(bathroom) @ 0x97300c8
||~Room(bedroom) @ 0x9730088