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

Effective C++ Item 47:Traits 技法實現編譯期型別特性查詢

     編輯:關於C++

什麼是 Traits

Traits 是一種編程慣例,利用模板與特化在**編譯期**提供型別相關資訊(如迭代器類別、大小、是否為 POD 等),支援泛型程式設計中的條件編譯邏輯。

經典案例:iterator_traits

問題背景

STL advance(iter, n) 需根據迭代器類別選擇最佳實作:

  • 隨機存取迭代器:iter += n (O(1))
  • 雙向/前向/輸入迭代器:循環 ++/-- (O(n))

但迭代器型別千變萬化,如何統一查詢其類別?

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 {};

繼承關係體現能力遞增,方便 is_base_of 檢查。

使用者定義型別:內嵌 typedef

template
class deque {
public:
    class iterator {
    public:
        typedef random_access_iterator_tag iterator_category; // 標記類別
        // ...
    };
};

全域 iterator_traits 統一介面

// 主模板:適用於有 iterator_category 的使用者型別
template
struct iterator_traits {
    typedef typename Iter::iterator_category iterator_category;
    typedef typename Iter::value_type value_type;
    typedef typename Iter::difference_type difference_type;
    typedef typename Iter::pointer pointer;
    typedef typename Iter::reference reference;
};

// 偏特化:原生指標 T*
template
struct iterator_traits {
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T* pointer;
    typedef T& reference;
};

// 偏特化:const T*
template
struct iterator_traits {
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef const T* pointer;
    typedef const T& reference;
};

advance 實作:標籤分派

// 主函數:提取 tag 並分派
template
void advance(Iter& iter, Dist n) {
    typename iterator_traits::iterator_category cat;
    __advance(iter, n, cat);  // 呼叫多載版本
}

// 隨機存取版本
template
void __advance(Iter& iter, Dist n, random_access_iterator_tag) {
    iter += n;
}

// 雙向版本
template
void __advance(Iter& iter, Dist n, bidirectional_iterator_tag) {
    if (n >= 0) while (n--) ++iter;
    else while (n++) --iter;
}

// 輸入迭代器版本(不支援負向)
template
void __advance(Iter& iter, Dist n, input_iterator_tag) {
    if (n < 0) throw out_of_range("Negative distance");
    while (n--) ++iter;
}

編譯器根據 cat 型別自動選擇正確多載,**零運行期開銷**。

建立自訂 Traits 的三步驟

  1. 確定需提供的資訊(如 iterator_category)。
  2. 命名該資訊(如 iterator_category)。
  3. 提供模板與必要特化(如 iterator_traits)。

標準庫其他 Traits

  • char_traits:字元操作特性。
  • numeric_limits:數值型別範圍與屬性。
  • type_traits (C++11):is_integral, is_class, remove_reference 等。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved