首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Effective C++ 條款 42:Traits 技術——編譯期類型資訊的提取與應用

     編輯:關於C++

背景:STL advance 的效能難題

advance(iter, d) 將迭代器移動 d 步。概念上是 iter += d,但只有 Random Access Iterator 支援 +=。弱一級的迭代器 (Bidirectional、Forward、Input) 必須迴圈呼叫 ++/--,線性時間。如何在編譯期依迭代器類型選擇最佳實作?

迭代器五大類別與 Tag 結構


struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

繼承關係反映能力層級:Forward 是 Input,Bidirectional 是 Forward,Random Access 是 Bidirectional。

Traits 技術核心:iterator_traits

Traits 非關鍵字,而是慣例與技術:以結構體模板儲存類型資訊,支援內建型別 (指標) 與用戶定義型別。

用戶定義迭代器:嵌套 typedef


class deque {
public:
    class iterator {
    public:
        typedef random_access_iterator_tag iterator_category;
        // ...
    };
};

指標類型:偏特化處理


template<typename IterT>
struct iterator_traits<IterT*> {
    typedef random_access_iterator_tag iterator_category;
    // ...
};

通用介面


template<typename IterT>
struct iterator_traits {
    typedef typename IterT::iterator_category iterator_category;
    // ...
};

編譯期分派:多載解析取代 runtime if

利用函式多載,編譯器依傳入的 tag 型別選擇正確實作:


// Random Access 版本
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::random_access_iterator_tag) {
    iter += d;
}

// Bidirectional 版本
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::bidirectional_iterator_tag) {
    if (d >= 0) while (d--) ++iter; else while (d++) --iter;
}

// Input/Forward 版本 (Forward 繼承 Input,自動複用)
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::input_iterator_tag) {
    if (d < 0) throw std::out_of_range("Negative distance");
    while (d--) ++iter;
}

// 主介面
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d) {
    doAdvance(iter, d,
        typename std::iterator_traits<IterT>::iterator_category());
}

Tag 物件 iterator_category() 僅作為多載解析的「鑰匙」,不佔用儲存空間。

Traits 設計模式總結

  1. 識別需提取的類型資訊 (如 iterator_category)。
  2. 命名資訊標識符。
  3. 提供主模板與特化 (含指標偏特化),包含所需資訊。
  4. 撰寫多載的 worker 函式,依 traits 參數實作不同邏輯。
  5. 撰寫 master 函式,提取 traits 並呼叫 worker。

標準庫其他 Traits

  • char_traits:字元型別特性。
  • numeric_limits:數值型別限制 (min/max/epsilon)。
  • TR1 引入 50+ 新 traits:is_fundamental、is_array、is_base_of 等。

核心心法

  • Traits 讓類型資訊在編譯期可用,透過模板與特化實現。
  • 結合多載,實現編譯期 if...else 型別分派,零執行期開銷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved