跳轉到內容

更多 C++ 慣用法/策略克隆

來自華夏公益教科書,開放的書籍,開放的世界

策略克隆

[編輯 | 編輯原始碼]

使用許多不同的可能型別例項化策略類,而不對策略類的型別進行臨時限制。

也稱為

[編輯 | 編輯原始碼]

使用基於策略的類設計技術可以構建高度可重用、靈活且可擴充套件的類。有時,策略的宿主類需要建立一個其例項化策略的精確副本,但使用不同的型別引數。不幸的是,宿主類模板的編寫者事先不知道要例項化的模板名稱。此外,策略類本身可能或可能不是模板。如果它是一個模板,則宿主類可能不知道例項化引數化策略類所需的最小型別引數數量。如果策略類不是模板,則它可能無法作為策略類參與。這種情況與工廠方法(GoF)模式非常類似,在這種模式中,要建立的物件的型別事先未知。

template <class Apolicy>
class Host
{
  Apolicy direct_policy_use;
  Apolicy <SomeInternalType> InternalClone;  // Problem 1: Can't do this
};

template <class T, template <class T> class Apolicy>
class Host2
{
  Apolicy <T> common_use;  
  Apolicy <SomeInternalType> InternalClone;  
  // Can do this now but 
  // Problem 2: policies that require more than one type parameter can't participate.
};

解決方案和示例程式碼

[編輯 | 編輯原始碼]

使用成員模板結構(稱為 rebind)將不同的型別引數傳遞給策略類模板。例如,

template <typename T>
class NiftyAlloc
{
  public:
    template <typename Other>
    struct rebind // The Policy Clone idiom
    { 
       typedef NiftyAlloc <Other> other;
    };
    //...
};

template <typename T, class Alloc = NiftyAlloc <T> >
class Vector 
{
  public:
    typedef typename Alloc::template rebind<long>::other ClonePolicy;
    // Here, Alloc may not be a template class or a parametrized instantiation of
    // a class that takes unknown number of type parameters.
};

這裡,Container 模板需要一個它例項化的分配策略的副本。因此,它使用 NiftyAlloc 策略公開的 rebind 機制。型別 Alloc::template rebind<long>::other 等同於 NiftyAlloc<long>。本質上,它表示:“我不知道此型別是什麼型別的分配器,也不知道它分配什麼,但我想要一個與它相同的分配器,它分配長整型。” 使用概念(它已從 C++0x 中刪除),Vector 類可以編寫型別概念,用於檢查 Alloc 策略型別是否支援 rebind 概念。

為了讓編譯器滿意,我們必須在 ClonePolicy typedef 中同時使用關鍵字 typename 和 template。規則如下:如果成員模板特化的名稱出現在 .、-> 或 :: 運算子之後,並且該名稱具有顯式限定的模板引數,則在成員模板名稱之前新增關鍵字 template。在 typedef 中也需要關鍵字 typename,因為 "other" 是一個型別,而不是一個變數。

已知用途

[編輯 | 編輯原始碼]
  • 標準模板庫
  • 不支援模板模板引數的編譯器
[編輯 | 編輯原始碼]

元函式包裝器慣用法 比策略克隆更強大。策略克隆慣用法以比元函式包裝器更抽象的方式指明其目的。rebind 模板本質上是元函式包裝器。

參考資料

[編輯 | 編輯原始碼]
華夏公益教科書