C++基本用法實踐之模板詳解
概述
C++的模板是泛型編程思想的一種實現(xiàn)。C++是強類型語言,處處強調類型。同樣的加法運算,int和float的加法運算需定義兩個函數(shù)(重載),而使用模板則可以只用一個函數(shù)(見下面示例)。
這類似我們面向對象所說的多態(tài)(定義加法運算,各個類型有不同的實現(xiàn)),所以是所謂靜多態(tài)的一種實現(xiàn)方式,不同的是,模板在編譯期展開生成int和float兩個加法函數(shù),如:
template<class T> T add(T a, T b) { return a + b; } int v1 = add<int>(1, 2); // 不顯式聲明模板參數(shù)類型,編譯器會試圖推斷 float v2 = add(1.5f, 2.5f); /* 實際上編譯器生成了兩個函數(shù) int add<int>(int a, int b) float add<float>(float a, float b) */
模板不光支持函數(shù)模板,還有類模板等,思想是一樣的(詳情見下面例子)。
模板還有一些特性機制如:模板特化,SFINAE(substitution failure is not an error 替換而非錯誤),變長參數(shù)模板等,另外模板在元編程中也是十分重要的組成部分,我對元編程沒有太多實踐,讀者有興趣可以自行搜索。
用法舉例
參考測試項目ModernCppTest/modrenc_template.cpp
主要內容:
- 函數(shù)模板&Lambda函數(shù)模板
- 類模板
- 別名模板
- 變量模板
- 值(枚舉)作為模板參數(shù)(其實int類型也可以)
- 模板特化
- 變長參數(shù)模板
- 模板函數(shù)的完美轉發(fā)
#include "ModernCppTestHeader.h" namespace n_template{ template <class T> void template_func(T t) { LOG_VAR(t); } template <class T> class Number { public: T v; Number(T v) : v(v) { LOG_VAR(v); } }; template <class T> constexpr T pi = T(3.1415926f); template <int INTVAL> void log_template_int_value() { LOG_VAR(INTVAL); } enum class EAnim : int { Other = 0, Cat = 1, Dog = 2, }; template<EAnim Ty> class Anim { public: void Bark() { LOG("默認:動物叫"); } }; template<> class Anim<EAnim::Dog> { public: void Bark() { LOG("狗:汪汪!"); } }; template<> class Anim<EAnim::Cat> { public: void Bark() { LOG("貓:喵喵!"); } }; // 注意遞歸基 void log_values() { LOG("展開結束"); } template<class T, class... ARGS> void log_values(T value, ARGS... args) { LOG(value); log_values(args...); } template<class T> void func_plus(T&& a) { auto v = a; LOG("func_plus v = " << a); } template<class T, class... ARGS> void func_plus(T&& a, T&& b, ARGS... args) { func_plus(a + b, std::forward<ARGS>(args)...); } template<class T> void func_mul(T&& a) { auto v = a; LOG("func_mul v = " << a); } template<class T, class... ARGS> void func_mul(T&& a, T&& b, ARGS... args) { func_mul(a + b, std::forward<ARGS>(args)...); } template <class... ARGS> void call_func(const std::string& name, ARGS&&... args) { if (name == "plus") func_plus(std::forward<ARGS>(args)...); else if (name == "mul") func_mul(std::forward<ARGS>(args)...); else LOG("Unknown function name: " << name); } } template<typename T> using Num = n_template::Number<T>; void template_test() { LOG_FUNC(); LOG_TAG(" 函數(shù)模板 "); { n_template::template_func(1); n_template::template_func(1.25f); LOG("Lambda 函數(shù)模板"); auto f = []<class T> (T t) { LOG_VAR(t); }; f(1); f(1.25f); } LOG_TAG("類模板"); { n_template::Number(1); n_template::Number(1.25f); } LOG_TAG("別名模板"); { Num<int>(1); Num<float>(1.25f); } LOG_TAG("變量模板"); { auto v1 = n_template::pi<int>; auto v2 = n_template::pi<float>; LOG_VAR(v1); LOG_VAR(v2); n_template::log_template_int_value<10>(); n_template::log_template_int_value<20>(); } LOG_TAG("枚舉變量模板&模板特化"); { n_template::Anim<n_template::EAnim::Dog>().Bark(); n_template::Anim<n_template::EAnim::Cat>().Bark(); LOG("EAnim::Other 沒有特化使用默認模板"); n_template::Anim<n_template::EAnim::Other>().Bark(); } LOG_TAG("變長參數(shù)模板"); { n_template::log_values("jack", 10, 3.14f); } LOG_TAG("變長參數(shù)模板的完美轉發(fā)"); { n_template::call_func("plus", 1, 2, 3, 4); n_template::call_func("mul", 2, 3); } }
到此這篇關于C++基本用法實踐之模板詳解的文章就介紹到這了,更多相關C++模板內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!