C++詳解非類型模板參數(shù)Nontype與Template及Parameters的使用
非類型類模板參數(shù)
前一章使用的例子 Stack
使用的是標準庫中的容器管理元素,也可以使用固定大小的 std::array
,它的優(yōu)勢是內(nèi)存管理開銷更小,數(shù)組的大小可以交給用戶指定。
#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(); }
使用該模板需要同時指定類型和個數(shù)。 Maxsize
用于指定 std::array
的大小。非類型模板參數(shù)也可以有默認值。
template<typename T = int, std::size_t Maxsize = 100> class Stack { ... };
非類型函數(shù)模板參數(shù)
也可以為函數(shù)定義非類型模板參數(shù)。
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
也可以指定一個模板參數(shù),由該參數(shù)之前的參數(shù)推斷出其類型。
template<auto Val, typename T = decltype(Val)> T foo();
或者保證傳值的類型和指定的類型相同。
template<typename T, T Val = T{}> T bar();
非類型模板參數(shù)的限制
需要注意的是,非類型模板參數(shù)有一定的限制。一般地,非類型模板參數(shù)可以是整形(包括枚舉)、指向?qū)ο?函數(shù)/成員的指針、對象/函數(shù)的左值引用或空指針類型 std::nullptr_t
。
浮點數(shù)和類類型對象不可以作為非類型模板參數(shù)。
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 ... };
當(dāng)使用指針或引用作為非類型模板參數(shù)時,不能用字符串字面值、臨時對象、數(shù)據(jù)成員或其他子對象作模板實參。
template<char const* name> class MyClass { ... }; MyClass<"hello"> x; // ERROR: string literal "hello" not allowed
C++版本逐漸放寬了限制。C+11 之前,對象必須有外部鏈接;C++17 之前對象必須有外部或內(nèi)部鏈接;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 }
非類型模板參數(shù)的實參可能是任何編譯期表達式。
template<int I, bool B> class C; ... C<sizeof(int) + 4, sizeof(int)==4> c;
當(dāng)表達式中使用了大于號,需要將整個表達式用小括號括起來。
C<42, sizeof(int) > 4> c; // ERROR: first > ends the template argument list C<42, (sizeof(int) > 4)> c; // OK
非類型模板參數(shù) auto
從 C++17 開始, 可以將非類型模板參數(shù)定義為 auto
,以接收任何允許作為非類型模板參數(shù)的類型。
#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 開始,已經(jīng)支持使用 auto 作為函數(shù)返回值。因此成員函數(shù) 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'; } }
前面說過,非類型模板參數(shù) auto
接收任何允許作為非類型模板參數(shù)的類型。
#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
的參數(shù)仍不能是浮點數(shù)。
Stack<int,3.14> sd; // ERROR: Floating-point nontype argument
使用 decltype(auto)
指定非類型模板參數(shù)的類型也是可以的。
template<decltype(auto) N> class C { ... }; int i; C<(i)> x; // N is int&
到此這篇關(guān)于C++詳解非類型模板參數(shù)Nontype與Template及Parameters的使用的文章就介紹到這了,更多相關(guān)C++非類型模板參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中rapidjson組裝map和數(shù)組array的代碼示例
今天小編就為大家分享一篇關(guān)于C++中rapidjson組裝map和數(shù)組array的代碼示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04C語言的數(shù)據(jù)結(jié)構(gòu)之樹、森連、二叉樹之間的轉(zhuǎn)換圖解
這篇文章主要介紹了C語言的數(shù)據(jù)結(jié)構(gòu)之樹、森連、二叉樹之間的轉(zhuǎn)換詳解,數(shù)據(jù)是信息的載體,是描述客觀事物屬性的數(shù)、字符以及所有能輸入到計算機中并被程序識別和處理的符號的集合,需要的朋友可以參考下2023-07-07VS2022 CUDA環(huán)境配置的實現(xiàn)步驟
本文主要介紹了VS2022 CUDA環(huán)境配置的實現(xiàn)步驟,文中通過圖文示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05