C++ Traits技術

來源:互聯網
上載者:User

標籤:

要想深入的理解STL的迭代器、分配器等,就必須瞭解C++模板編程中的一個技巧——Traits。

1、問題的提出

C++的模板特性為泛型程式設計提供了支援。這樣我們就可以編寫更加通用的代碼,而不必過分去關心參數的類型。然而事實卻是,類型的不同,很多時候卻影響到了演算法中的某個小小的實現。舉個標準庫裡的類string,wstring。

其實它們對應的是兩個模板,前者單字元,後者寬字元。

typedef basic_string<char, char_traits<char>, allocator<char> > string;typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring;

 

模板basic_string需要有一個得出字串長度的函數length,那麼問題就來了。因為char和wchar_t所對應的求長度API並不一樣。前者是strlen,後者是wcslen。

正是為瞭解決這樣類似的問題,C++中的traits技巧被提煉出來了。

2、解決方案

因為模板參數的類型不同,可能會影響到模板中具體的演算法,那麼我們就需要把這些與模板參數相差的方法從模板basic_string中提取出來,而保證basic_string演算法的一致不受參數類型不同的影響。而上面的char_traits模板即是把與模板參數相差的方法都封裝起來了。如果定義這樣一個模板.

template<class _Elem>struct char_traits{static void __CLRCALL_OR_CDECL assign(_Elem& _Left, const _Elem& _Right){        // assign an element_Left = _Right;}static bool __CLRCALL_OR_CDECL eq(const _Elem& _Left, const _Elem& _Right){        // test for element equalityreturn (_Left == _Right);}//……//……//…..static size_t __CLRCALL_OR_CDECL length(const _Elem *_First){        // find length of null-terminated sequence//                _DEBUG_POINTER(_First);size_t _Count;for (_Count = 0; !eq(*_First, _Elem()); ++_First)++_Count;return (_Count);}};

這裡的legnth實現是一個通用演算法迴圈遍曆,並沒有使用系統的strlen,wcslen,效率相對低一些。那麼如果我一定要使用strlen,wcslen呢?

這裡就需要用到模板的特化,也即指定模板的參數類型。

        // STRUCT char_traits<wchar_t>    template<> struct  char_traits<wchar_t>          {    // properties of a string or stream wchar_t element    static void __CLRCALL_OR_CDECL assign(_Elem& _Left, const _Elem& _Right)        {    // assign an element        _Left = _Right;        }    static bool __CLRCALL_OR_CDECL eq(const _Elem& _Left, const _Elem& _Right)        {    // test for element equality        return (_Left == _Right);        }        ……        ……        …..    static size_t __CLRCALL_OR_CDECL length(const _Elem *_First)        {    // find length of null-terminated sequence    //        _DEBUG_POINTER(_First);        return (::wcslen(_First));        }    };            // STRUCT char_traits<char>    template<> struct  char_traits<char>              {    // properties of a string or stream wchar_t element    static void __CLRCALL_OR_CDECL assign(_Elem& _Left, const _Elem& _Right)        {    // assign an element        _Left = _Right;        }    static bool __CLRCALL_OR_CDECL eq(const _Elem& _Left, const _Elem& _Right)        {    // test for element equality        return (_Left == _Right);        }        ……        ……        …..    static size_t __CLRCALL_OR_CDECL length(const _Elem *_First)        {    // find length of null-terminated sequence    //        _DEBUG_POINTER(_First);        return (::strlen(_First));        }    };

當實現了上面兩個特化的模板之後,在模板basic_string中,我們如果需要知道當前模板參數類型的字串長度時,只需要調用char_traits::length()就可以調用到正確的函數了。

3、總結

通過以上的案例,我們可以看出,具體的traits技巧非常簡單。也就是將因為模板形參(包括類型形參、非類型形參)不同而導致的不同,抽取到新的模板中去,然後通過模板的特化(全特化、偏特化均可,至少有一個模板形參不同即可)來分別實現其不同。 這一類的模板,都會在命名中加上traits以示區別,所以也會把運用這一類方法稱為C++的traits技術。traits技術更展現出了一種編程的思想,也即將相同的提出複用,將不同的部分通過介面來實現。將模板形參與基不同的實現綁定在一起,其實與設計模式中的狀態模式很相似,都體現出了相同的編程思想。只不過前者是編譯時間確定的,後者則是運行時確定的。

4、注意

  1. Boost中有這樣一個例子。
    template< typename T > struct is_pointer{ static const bool value = false; };template< typename T > struct is_pointer< T* >{ static const bool value = true; };

    這樣我就可以通過is_pointer<T>::value來判斷當前類型是否為指標類型。

  2. 非類型模板形參

    Template<bool b>Struct algo_sort{  Template<typename T>  Static void sort(T& obj)  {     Quick_sort(obj);  }}Template<>Struct algo_sort<true>{  Template<typename T>  Static void sort(T& obj)  {     Select_sort(obj);  }}

    這樣就能夠模板形參調用不同的排序方法了.

  3. 模板形參不僅僅與變數方法有關,還可能與類型有類.

    template< typename T >struct STRUCT_TYPE{   typedef int MY_TYPE;   typedef LONGLONG POWER_TYPE;};template<>struct STRUCT_TYPE<double>{    typedef float MY_TYPE;    typedef double POW_TYPE;};template< typename T > struct STRUCT_ALGO{   // 下面的Typename是指示T::MY_TYPE是一個類型而不是成員變數   // 在VS2005中加與不加均可   typedef typename T::MY_TYPE myType;   typedef T::POWER_TYPE powType;            powType GetPow(const myType& value)    {       return value*value;    }};

    這樣我們甚至可以將模板形參關聯的變數類型也可以抽離出來,以提高模板的通用性.

C++ Traits技術

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.