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
...
};當使用指針或引用作為非類型模板參數(shù)時,不能用字符串字面值、臨時對象、數(shù)據(jù)成員或其他子對象作模板實參。
template<char const* name>
class MyClass {
...
};
MyClass<"hello"> x; // ERROR: string literal "hello" not allowedC++版本逐漸放寬了限制。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;
當表達式中使用了大于號,需要將整個表達式用小括號括起來。
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++中右值引用和移動構(gòu)造函數(shù)的使用
這篇文章主要是來和大家一起聊聊C++中右值引用和移動構(gòu)造函數(shù)的使用,文中通過示例進行了詳細講解,感興趣的小伙伴可以跟隨小編一起學習一下2022-07-07
C++連接mysql數(shù)據(jù)庫的兩種方法小結(jié)
這篇文章主要介紹了C++連接mysql數(shù)據(jù)庫的兩種方法小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04

