模板類中定義模板函式

2021-06-28 16:50:39 字數 3178 閱讀 7717

用模板類和模板函式是c++程式猿必須掌握的技能。然而要充分運用編譯器的推導能力則不簡單。

需求:建立乙個**類, 每一列的型別可以任意指定(編譯期指定),每一行的元素可以任意指定(執行期確定)。列數可變(編譯期指定),行數可變(執行期確定)。

這裡特意強調了編譯期和執行期,就是為了最大程度利用編譯器的推導能力,進行編譯期計算,以達到(接近)最高效率。

so, let『s begin!!

將任務拆解,顯然每列元素可以直接用stl的各種容器完成,這裡暫時放下不表;行元素咋辦呢?

task1: 列數可變,但是在編譯器能確定。

這裡用到了c++11的variadic template

特性。雖然之前也可以支援這種類似的寫法,但是各種巨集很容易把猿猿搞暈。還是新標準來得清爽。

// generic of typelist

template struct typelist{};

// specific of typelist

template <>

struct typelist<>{};

// partial specific of typelist

template struct typelist: public typelist

};int main()

// output:

// type: d

// type: c

// type: i

通過(編譯期)遞迴形式達到型別和數量都可變的目的。

task2: 如何獲得第i列的型別, 好為get函式做準備?

// traits: typeofindextemplate struct typeofindex

;template struct typeofindex<0, _typelist>

;

非常優雅的完成了型別任務,以後只要寫typeofindex::value_type 就可以了。

task3: 獲取值的get函式如何定義,如何實現?

這個問題折騰了猿猿一整天。先看看我的容器定義吧:

// generic of valuetable

template class valuetable/* : public valuetable>*/{};

// specific of valuetable

template <>

class valuetable<>{}; // boundry

// specific of valuetable

template <>

class valuetable>{};

// valuetable offers real value (at runtime)

template class valuetable> :

public valuetable::tail_typelist>

;

第乙個類是通式,沒啥東西,就是告訴編譯器:有這麼個東西叫valuetable,接收任何數量任何型別的引數的模板類。

第二和第三個是邊界,類似遞迴出口,不解釋。

第四個是真正的容器定義類,也是所有資料的儲存地點。

那麼,問題就來了:某個valuetable怎麼去獲取指定索引的值呢?

看看我們手頭有的東西:有個通過type_list和列索引轉換到指定列型別的」函式「,列索引colindex(編譯期知道),行索引(執行期知道)。那麼我們就通過這些來寫出函式宣告:

templatetypename typeofindex::value_type get(size_t keyindex) const;

注意這裡的輸入引數只有兩個: colindex和keyindex(可以看成rowindex,這裡命名成這個樣子是有其它用途)。

有關實現這個函式。如果傳入的colindex為0,那麼直接返回當前的m_val[keyindex]就可以;否則,就在父類中遞迴找colindex-1的值。

templatetypename typeofindex::value_type get(size_t keyindex) const

template<>

typename typeofindex<0, type_list>::value_type get(size_t keyindex) const

看上去很美好,貌似任務都完成了。g++ -std=c++11 -c valuetable.cpp 試試?

不好,編譯器報error!!難道是**寫錯了?如果是rtti**,寫錯了在編譯器也不知道,只有在執行時候才能看出些東西來。對於剛接觸generic programming的猿猿來說還真不敢保證一定是對的。於是各種排查問題……(一下省略500字)

終於在stackoverflow中找到了答案:原來在模板類中是不允許進行成員函式的特化的,因為編譯器並不知道到底要特化的是哪乙個model的成員函式。而且更加悲催的是vc程式猿編譯這些**居然可以通過!! 微軟又大坑了一把各位猿猿們啊!!

ok,原因找到了,那麼到底怎麼實現呢?萬能的stackoverflow告訴猿猿,可以採用函式過載的方法實現。寫兩個輔助函式,作為private函式就好了。當然,要過載就必須型別(簽名)不同,那就在內部再加上乙個identity型別標記好了。

// identity mark

template struct identity{};

public:

templatetypename typeofindex::value_type get(size_t keyindex) const

private:

// override function of get implement

templatetypename typeofindex::value_type get_aux(size_t keyindex, identity) const

// specific of gettypename typeofindex<0, type_list>::value_type get_aux(size_t keyindex, identity<0>) const

終於大功告成,編譯通過。執行結果猿猿還沒有測試。以上方法僅供參考。

C 中的模板(類模板 模板類 模板函式)

1 class 一般class用於定義類,在模板引入c 後,最初定義模板的方法為 template,這裡class關鍵字表明t是乙個型別 2 typename 為了避免class在這兩個地方的使用可能給人帶來混淆,所以引入了typename這個關鍵字,它的作用同class一樣表明後面的符號為乙個型別...

類模板,模板類和函式模板,模板函式

單整數類 雙整數類 所以c艹跟其他強型別語言為我們提供了乙個所謂模版功能 變數型別 整數 類模板的重點是模板。表示的是乙個模板,專門用於產生類的模子。例子 1 template 2 class vector 3 使用這個vector模板就可以產生很多的class 類 vector vector ve...

c 模板類如何定義模板成員函式

最近跟網上乙個解決乙個模板問題 其實他在用g 編譯器寫模板定義成員函式,我在vs 05的c 編譯器上寫,然後我測試模板的結果是 特例模板不可以在類外定義,不管是在標頭檔案還是cpp檔案都要報錯,然後跟他說讓他寫在類中 當時不知道他在用g 編譯器 於是悲劇的問題出來了 他那個老是報沒在未命名空間類域中...