測試容器中成員身分

由於節點儲存空間是容器中現有物件的屬性,因此可以檢查物件本身,以確認該物件目前是否包含在容器中。這項檢查一律是一項快速的 O(1) 作業。

本指南的章節將說明不同的方法,讓您測試物件目前是否屬於該容器目前所含的任何容器成員。

使用 Mix-ins 測試單一容器物件

所有節點狀態類別都提供一個公開的 InContainer() 方法,可用於測試節點狀態執行個體目前是否為該容器的成員,以及物件通常衍生自的 ListableContainable 混合。由於物件衍生自混用物件,因此也會公開此方法,因此測試使用混合項目,而且只能是單一容器的成員,就像在物件上呼叫 InContainer() 一樣簡單。

class Obj : public fbl::SinglyLinkedLisable<Obj*> { /* ... */ };

Obj* the_obj = new Obj();
fbl::SinglyLinkedList<Obj*> the_list;
ASSERT(the_obj->InContainer() == false);

the_list.push_front(the_obj);
ASSERT(the_obj->InContainer() == true);

the_list.clear();
ASSERT(the_obj->InContainer() == false);

delete the_obj;

使用混合函式的多個容器物件,不含 ContainableBaseClasses

如果物件衍生自多個混合項目,因此可以成為多個容器的成員,情況可能會變得比較複雜。物件本身現在有多個 InContainer() 的實作,而這些實作是從混合使用項目而來,因此呼叫端必須明確說明要呼叫的函式。儘管這種做法的確可以避免,但語法在物件上的自訂方法中,可能還是很有用。例如:

class Obj : public fbl::DoublyLinkedListable<Obj*>,
            public fbl::WAVLTreeContainable<Obj*> {
 public:
   // ...
   bool InList() const { return this->DoublyLinkedListable<Obj*>::InContainer(); }
   bool InTree() const { return this->WAVLTreeContainable<Obj*>::InContainer(); }
   // ...
};

void test(const Obj& obj) {
  bool in_list, in_tree;

  // The hard way
  in_list = obj.DoublyLinkedListable<Obj*>::InContainer();
  in_tree = obj.WAVLTreeContainable<Obj*>::InContainer();

  // The slightly easier way (the class still needs to implement the hard way)
  in_list = obj.InList();
  in_tree = obj.InTree();
}

使用混合項目的多個容器物件,支援 ContainableBaseClasses

您可以同時將 ContainableBaseClasses 用於多個容器中的現有容器,這樣就能更輕鬆地使用標記,藉此選取要測試成員資格的容器。fbl:: 提供獨立的 InContainer 函式,可與標記搭配使用,以便更輕鬆地測試成員資格。我們來看看前一個範例,但這次是使用 ContainableBaseClasses

struct ListTag {};
struct TreeTag {};

class Obj
  : public fbl::ContainableBaseClasses<fbl::TaggedDoublyLinkedListable<Obj*, ListTag>,
                                       fbl::TaggedWAVLTreeContainable<Obj*, TreeTag>> { /* ... */ };

void test(const Obj& obj) {
  bool in_list = fbl::InContainer<ListTag>(obj);
  bool in_tree = fbl::InContainer<TreeTag>(obj);
}

直接使用 NodeState 物件進行測試

最後,在使用 NodeState 物件和自訂特徵的情況下,仍可測試容器成員資格,但您必須直接詢問 NodeState 執行個體。

class Obj {
 public:
  // Obj impl here

  bool InFooList() const { return foo_list_node_.InContainer(); }
  bool InBarList() const { return bar_list_node_.InContainer(); }

 private:
  struct FooListTraits {
    static auto& node_state(Obj& obj) {
      return obj.foo_list_node_;
    }
  };

  struct BarListTraits {
    static auto& node_state(Obj& obj) {
      return obj.bar_list_node_;
    }
  };

  friend struct FooListTraits;
  friend struct BarListTraits;

  fbl::DoublyLinkedListNodeState<Obj*> foo_list_node_;
  fbl::DoublyLinkedListNodeState<fbl::RefPtr<Obj>> bar_list_node_;

 public:
  using FooList = fbl::DoublyLinkedListCustomTraits<Obj*, FooListTraits>;
  using BarList = fbl::DoublyLinkedListCustomTraits<fbl::RefPtr<Obj>, BarListTraits>;
};