<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
前一章使用的例子 Stack
使用的是標準庫中的容器管理元素,也可以使用固定大小的 std::array
,它的優勢是記憶體管理開銷更小,陣列的大小可以交給使用者指定。
#include <array> #include <cassert> template<typename T, std::size_t Maxsize> class Stack { private: std::array<T,Maxsize> elems; // elements std::size_t numElems; // current number of elements public: Stack(); // constructor void push(T const& elem); // push element void pop(); // pop element T const& top() const; // return top element bool empty() const { // return whether the stack is empty return numElems == 0; } std::size_t size() const { // return current number of elements return numElems; } }; template<typename T, std::size_t Maxsize> Stack<T,Maxsize>::Stack () : numElems(0) // start with no elements { // nothing else to do } template<typename T, std::size_t Maxsize> void Stack<T,Maxsize>::push (T const& elem) { assert(numElems < Maxsize); elems[numElems] = elem; // append element ++numElems; // increment number of elements } template<typename T, std::size_t Maxsize> void Stack<T,Maxsize>::pop () { assert(!elems.empty()); --numElems; // decrement number of elements } template<typename T, std::size_t Maxsize> T const& Stack<T,Maxsize>::top () const { assert(!elems.empty()); return elems[numElems-1]; // return last element } int main() { Stack<int,20> int20Stack; // stack of up to 20 ints Stack<int,40> int40Stack; // stack of up to 40 ints Stack<std::string,40> stringStack; // stack of up to 40 strings // manipulate stack of up to 20 ints int20Stack.push(7); std::cout << int20Stack.top() << 'n'; int20Stack.pop(); // manipulate stack of up to 40 strings stringStack.push("hello"); std::cout << stringStack.top() << 'n'; stringStack.pop(); }
使用該模板需要同時指定型別和個數。 Maxsize
用於指定 std::array
的大小。非型別模板引數也可以有預設值。
template<typename T = int, std::size_t Maxsize = 100> class Stack { ... };
也可以為函數定義非型別模板引數。
template<int Val, typename T> T addValue (T x) { return x + Val; } std::transform (source.begin(), source.end(), // start and end of source dest.begin(), // start of destination addValue<5,int>); // operation
也可以指定一個模板引數,由該引數之前的引數推斷出其型別。
template<auto Val, typename T = decltype(Val)> T foo();
或者保證傳值的型別和指定的型別相同。
template<typename T, T Val = T{}> T bar();
需要注意的是,非型別模板引數有一定的限制。一般地,非型別模板引數可以是整形(包括列舉)、指向物件/函數/成員的指標、物件/函數的左值參照或空指標型別 std::nullptr_t
。
浮點數和類型別物件不可以作為非型別模板引數。
template<double VAT> // ERROR: floating-point values are not double process (double v) // allowed as template parameters { return v * VAT; } template<std::string name> // ERROR: class-type objects are not class MyClass { // allowed as template parameters ... };
當使用指標或參照作為非型別模板引數時,不能用字串字面值、臨時物件、資料成員或其他子物件作模板實參。
template<char const* name> class MyClass { ... }; MyClass<"hello"> x; // ERROR: string literal "hello" not allowed
C++版本逐漸放寬了限制。C+11 之前,物件必須有外部連結;C++17 之前物件必須有外部或內部連結;C++17 放開了此限制。
extern char const s03[] = "hi"; // external linkage char const s11[] = "hi"; // internal linkage int main() { MyClass<s03> m03; // OK (all versions) MyClass<s11> m11; // OK since C++11 static char const s17[] = "hi"; // no linkage MyClass<s17> m17; // OK since C++17 }
非型別模板引數的實參可能是任何編譯期表示式。
template<int I, bool B> class C; ... C<sizeof(int) + 4, sizeof(int)==4> c;
當表示式中使用了大於號,需要將整個表示式用小括號括起來。
C<42, sizeof(int) > 4> c; // ERROR: first > ends the template argument list C<42, (sizeof(int) > 4)> c; // OK
從 C++17 開始, 可以將非型別模板引數定義為 auto
,以接收任何允許作為非型別模板引數的型別。
#include <array> #include <cassert> template<typename T, auto Maxsize> class Stack { public: using size_type = decltype(Maxsize); private: std::array<T,Maxsize> elems; // elements size_type numElems; // current number of elements public: Stack(); // constructor void push(T const& elem); // push element void pop(); // pop element T const& top() const; // return top element bool empty() const { // return whether the stack is empty return numElems == 0; } size_type size() const { // return current number of elements return numElems; } }; // constructor template<typename T, auto Maxsize> Stack<T,Maxsize>::Stack () : numElems(0) // start with no elements { // nothing else to do } template<typename T, auto Maxsize> void Stack<T,Maxsize>::push (T const& elem) { assert(numElems < Maxsize); elems[numElems] = elem; // append element ++numElems; // increment number of elements } template<typename T, auto Maxsize> void Stack<T,Maxsize>::pop () { assert(!elems.empty()); --numElems; // decrement number of elements } template<typename T, auto Maxsize> T const& Stack<T,Maxsize>::top () const { assert(!elems.empty()); return elems[numElems-1]; // return last element }
從 C++14 開始,已經支援使用 auto 作為函數返回值。因此成員函數 size()
可以簡寫為:
auto size() const { // return current number of elements return numElems; }
上述模板的使用:
int main() { Stack<int,20u> int20Stack; // stack of up to 20 ints Stack<std::string, 40> stringStack; // stack of up to 40 strings // manipulate stack of up to 20 ints int20Stack.push(7); std::cout << int20Stack.top() << 'n'; auto size1 = int20Stack.size(); stringStack.push("hello"); std::cout << stringStack.top() << 'n'; auto size2 = stringStack.size(); if (!std::is_same_v<decltype(size1), decltype(size2)>) { std::cout << "size types differ" << 'n'; } }
前面說過,非型別模板引數 auto
接收任何允許作為非型別模板引數的型別。
#include <iostream> template<auto T> // take value of any possible nontype parameter (since C++17) class Message { public: void print() { std::cout << T << 'n'; } }; int main() { Message<42> msg1; msg1.print(); // initialize with int 42 and print that value:42 static char const s[] = "hello"; Message<s> msg2; // initialize with char const[6] "hello" msg2.print(); // and print that value:hello }
非型別模板 auto
的引數仍不能是浮點數。
Stack<int,3.14> sd; // ERROR: Floating-point nontype argument
使用 decltype(auto)
指定非型別模板引數的型別也是可以的。
template<decltype(auto) N> class C { ... }; int i; C<(i)> x; // N is int&
到此這篇關於C++詳解非型別模板引數Nontype與Template及Parameters的使用的文章就介紹到這了,更多相關C++非型別模板引數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45