H_On Template - H_On 自制程序模板推薦

HT-H_On 模板【ps:希望有朝一日能出一個HTL(H_On 標準模板庫)呢 嘿嘿

起源

要說起猹開發這些模板的原因呢~一個是大家也知道,猹這個寒假更新了STL的介紹,兩篇!可以說是人生第一次經歷了大量練習獲得了很多知識

tired
要說直接原因,就是昨天打 CF 的時候 sages7 給我推薦了一個好用的 cf 小工具,可以自動爬取比賽題對外的測試數據,還可以用命令測試提交代碼。然後它支持在生成的題目文件夾裏生成一個編程代碼模板,這個是自己給定的。正好我早就想優化一下我的那些亂七八糟的代碼了,於是趁此機會,整活一天終於獲得了一些收穫,現在迫不及待的開始寫分享博客了owo

其實我想優化代碼的想法很久了,不知道大家有沒有遇到這種情況,有時候會經常時不時的就需要寫一些比較結構體,用來讓 set 按降序排列,可是有時候是排 int 元素有時候是 long long 還有時候甚至是 string ,那麼就算把比較結構體的大框架留下來,每次使用都可能需要修改一堆變量類型名,由於 STL 那些容器都可以隨意的設置元素的變量類型,所以我也想整一個全類型通用比較結構體。

實際上以前什麼兩數交換啊,求兩個數的最小公倍數這兩個函數,猹也都是憨憨每次都自己手寫,也經常因爲變量類型不通用而煩惱。於是這次我找了好多網頁,甚至查閱了源代碼,最終初窺門徑了!

先說說比較好用但其實沒啥用的交換函數

這個函數是真的,很簡單,但是每次對於不同的變量都要重寫真的好麻煩(要改三個地方的變量類型呢),於是我先研究的這個。

template <class H_On> void EX(H_On &a, H_On &b) {
        H_On t = a;
        a = b;
        b = t;
}

H_On 的地方就是每次要交換的變量類型不一樣的地方要改的,尤其是經歷了昨晚我在最後一分鐘交了一道題,還沒判過比賽就結束了,但最後是 AC 之後,我真心感覺能節約幾秒都是好的,可是總是改真的很煩啊,經歷過就知道辣 > m <

總而言之呢,這樣子一來,我再無論怎麼用 EX() 這個函數,不管丟進去什麼類型的變量都可以互換辣,開心。

ps:其實 <algorithm> 庫裏有一個函數叫 swap() ,底層就是用這種模板類型的方式實現的,甚至對整型變量還有特異優化。這個函數也是我在 跟 sages7 討論我的想法的時候跟我說的 消磨猹探索積極性的 sages7 是屑,還好他沒成功

然後是也沒啥用的求最大公約數函數

這個函數的話也是時不時就會用到的,但是會遇到有時候用 int 有時候用 long long 所以其實也是有這個需求的。

template <class H_On> H_On GCD(H_On a, H_On b) {
        if (!b) return a;
        if (!a) return b;
        while (b) {
                H_On t = a % b;
                a = b;
                b = t;
        }
        return a;
}

跟上面那個類似只不過 還多了一個返回值,然後爲什麼說沒用呢,因爲其實 <algorithm> 庫裏還有一個函數 __gcd() 也是可以求最大公約數的

比較重要的 - 自定義比較結構體和一些常數的定義

STL 常備自定義比較結構體

我們在使用 set/multiset 容器的時候經常會遇到需要將默認升序排序變成降序排序的情況,而同樣的,就算是我們只保留簡單的換順序的排序規則,也時常遇到變量類型要換的情況,所以這裏給出了這個,同樣是用模板類實現的

template <class H_On_compT> struct hon_cmp {
        bool operator () (const H_On_compT &a, const H_On_compT &b) {
                return a > b;
        }
};

這時候直接寫 set<T, hon_cmp<T>> 即可,注意,要寫兩個變量類型而且要一樣

例如:set<int, hon_cmp<int>> s; 這樣子再往集合容器 s 中插入元素時就會默認是升序排列啦。

常用常數的多類型定義

同樣是 int 和 long long 的問題,但是這裏要注意,因爲不是函數而是直接獲取一個變量,或者說我需要直接獲取一個數,一個固定值,所以這裏我用了另一種方式,就是使用模板變量的形式然後使用類來生成一個對象,作爲我們需要的變量

template <typename H_On_infnT> class infn {
        public:
                H_On_infnT N;
                infn(H_On_infnT honValue) {
                        this->N = honValue;
                }
        };
template <typename H_On_maxnT> class maxn {
        public:
                H_On_maxnT N;
                maxn(H_On_maxnT honValue) {
                        this->N = honValue;
                }
        };

這裏要簡單的介紹一下使用方法,有點不太好探索

infn<int> INF(int(1e9 + 9));
maxn<string> MAX("nihao");
cout << "inf = " << INF.N << endl;
cout << "max = " << MAX.N << endl;

輸出就長這樣

inf = 1000000009
max = nihao

如你所見,支持全類型的特殊功能定義。

閒言碎語

最後還是猹的無聊自言自語,猹其實是喜歡把所有常用的東西都寫上,但是爲了明確我用到了哪那個功能,會把所有的東西都儘量寫成一行,然後用到哪行把哪行註釋掉,如下所示是猹完成的模板

#include <iostream>
using namespace std;
//#include <cmath>
//#include <set>
//#include <map>        //map<int, int, greater<int>> m;
//#include <stack>
//#include <vector>
//#include <deque>
//#include <bitset>
//#include <algorithm>  //__gcd(), swap()
//#include <iomanip>
//#define dfos(outStep) fixed << setprecision(outStep)

//typedef long long ll;

//template <typename H_On_infnT> class infn {public: H_On_infnT N; infn(H_On_infnT honValue) {this->N = honValue;}};
//template <typename H_On_maxnT> class maxn {public: H_On_maxnT N; maxn(H_On_maxnT honValue) {this->N = honValue;}};
//template <class H_On_compT> struct hon_cmp {bool operator () (const H_On_compT &a, const H_On_compT &b) {return a > b;}};

int main() {
        ios::sync_with_stdio(0); cin.tie(0);
        int t; cin >> t;
        while (t--) {

        }
        return 0;
}

可以看到,全部都一行註釋掉,還會加一些暫時不熟練的用法或者函數的註釋,然後用到那個函數庫或者預定義就取消掉註釋,實在不喜歡有些人提交的代碼有很多沒用的東西,當然這只是個人看法。沒準有一天猹也會因爲覺得麻煩而提交一大堆沒用的代碼,誰知道呢 =w=

最主要的是希望各位如果還是比較新手的階段,不要對知識不求甚解,僅僅知道用法不知道原理,這樣是不對的。

今天一整天,爲了做這個查了好多人家的文章,還翻了幾個小時的底層實現 vector 啊什麼的容器的源代碼,總算是搞清了一點點 “模板” 的工作原理,總歸做出來了還是挺開心的

最後祝大家學習快樂,天天進步 揮揮~

請多多支持猹的個人博客 H_On 個人小站 啊啊啊~拜託惹 > ~ <
因爲猹的小站真的還挺可的,所以那邊更新的也比較勤奮,感謝關注~我會努力的(ง •_•)ง

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章