如何在C++项目中实现模板中的非类型参数-创新互联

这篇文章给大家介绍如何在C++项目中实现模板中的非类型参数,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

10余年建站经验, 成都做网站、网站设计客户的见证与正确选择。创新互联建站提供完善的营销型网页建站明细报价表。后期开发更加便捷高效,我们致力于追求更美、更快、更规范。

非类型模板参看,顾名思义,模板参数不限定于类型,普通值也可作为模板参数。在基于类型的模板中,模板实例化时所依赖的是某一类型的模板参数,你定义了一些模板参数(template)未加确定的代码,直到模板被实例化这些参数细节才真正被确定。而非类型模板参数,面对的未加确定的参数细节是指(value),而非类型。当要使用基于值的模板时,你必须显式地指定这些值,模板方可被实例化。


在函数模板中使用非类型参数

#include
using namespace std;
//在函数模板中使用非类型参数
templatevoid Swap(T &a, T &b);
templatevoid Swap(T (&a)[N],T (&b)[N]);

templatevoid printArray(T (&arr)[N]);

int main(){
 int m = 10, n = 90;
 Swap(m,n);
 cout << "m = " << m << ", n = " << n << endl;

 int a[5] = { 1, 2, 3, 4, 5 };
 int b[5] = { 10, 20, 30, 40, 50 };
 Swap(a, b);
 printArray(a);
 printArray(b);
 return 0;

}

template void Swap(T &a,T &b){
 T temp = a;
 a = b;
 b = temp;
}

template void Swap(T (&a)[N],T (&b)[N]){
 T temp;
 for (int i = 0; i < N;i++){
 temp = a[i]; 
 a[i] = b[i];
 b[i] = temp;
 }
}

templatevoid printArray(T (&arr)[N]){
 for (int i = 0; i < N;i++){
 if (i == N-1){
  cout << arr[i] << endl;
 }
 else{
  cout << arr[i] << ", ";
 }
 }
}

在类模板中使用非类型参数

#include
#include
#include
using namespace std;

//动态数组实现,在类模板中使用非类型参数
template
class Array{
public:
 Array();
 ~Array();
public:
 T & operator[](int i);//重载下标运算符
 int length() const{ return m_length; }//获取数组长度
 bool capacity(int n);//是否可改变数组容量
private:
 int m_length;//数组当前长度
 int m_capacity;//当前内存容量
 T *m_p;//指向数组内存的指针
};

template
Array::Array(){
 m_p = new T[N];
 m_capacity = m_length = N;
}

template
Array::~Array(){
 delete[] m_p;
}

template
T & Array::operator[](int i){
 if (i<0||i>=m_length){
 cout << "Exception:Array index out of bounds!" << endl;
 }
 return m_p[i];
}

template
bool Array:: capacity(int n){
 if (n>0){
 int len = m_length + n;
 if (len<=m_capacity){
  m_length = len;
  return true;
 }
 else{
  T *pTemp = new T[m_length + 2 * n*sizeof(T)];
  if (NULL==pTemp){
  cout << "Exception: Failed to allocate memory!";
  return false;
  }
  else{ 
  memcpy(pTemp,m_p,m_length*sizeof(T));
  delete[] m_p;
  m_p = pTemp;
  m_capacity = m_length = len;
  }
 }
 }
 else{
 int len = m_length - abs(n);
 if (len<0){
  cout << "Exception:Array length is too small!" << endl;
  return false;
 }
 else{
  m_length = len;
  return true;
 }
 }
}

int main(){
 Array arr;

 for (int i = 0, len = arr.length(); i < len;i++){
 arr[i] = 2 * i;
 }

 cout << "first print:" << endl;
 for (int i = 0, len = arr.length(); i < len;i++){
 cout << arr[i] << " ";
 }
 cout << endl;

 //扩大容量为增加的元素赋值
 arr.capacity(8);
 for (int i = 5, len = arr.length(); i < len;i++){
 arr[i] = 2 * i;
 }

 cout << endl;
 cout << "second print:" << endl;
 for (int i = 0, len = arr.length(); i < len;i++){
 cout << arr[i] << " ";
 }
 cout << endl;

 arr.capacity(-4);
 cout << "third print: " << endl;
 for (int i = 0, len = arr.length(); i < len; i++){
 cout << arr[i] << " ";
 }
 cout << endl;

 return 0;
}

非类型模板参数的限制

非类型模板参数是有类型限制的。一般而言,它可以是常整数(包括enum枚举类型)或者指向外部链接对象的指针。

浮点数和类对象(class-type)不允许作为非类型模板参数:

template      // ERROR: 浮点数不可作为非类型模板参数
double process(double v)
{
  return v * VAL;
}

template   // ERROR:类对象不能作为非类型模板参数
class MyClass
{}


稍作变通,我们即可使编译通过:

template
double process(const double& x)
{
  return x * (*PVAL);
}

template
class MyClass
{
  ...
}

这样可顺利通过编译,但如果想在当前文件中使用这两个模板,还需要动一些手脚:

double val = 10;
double res = process<&val>(20);   // ERROR: 表达式必须含有常量值

MyClass<"hello"> x;         // ERROR: 模板参数不能引用非外部实体

const char* s = "hello";
MyClass x;            // ERROR: 表达式必须含有常量值

这里就点出另外一点注意事项,也就是非类型模板参数的限制,非类型模板参数可以是指针,但该指针必须指向外部链接对象,还记得在A.cpp中如何引用B.cpp中的全局变量吗,在A.hpp中使用extern关键字对外部变量加以引用。

// B.cpp
double val = 3.14159265;
char str[] = "hello";
// A.hpp
extern double val;
extern char str[];
// A.cpp
#include "A.hpp"

double res = process<&val>(10);
MyClass x;

关于如何在C++项目中实现模板中的非类型参数就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。


当前名称:如何在C++项目中实现模板中的非类型参数-创新互联
文章源于:http://scyanting.com/article/djcpgs.html