非类型模板参数

对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数。在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定。但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化。

非类型的类模板参数

创建类的头文件

#include<stdexcept>
#include<iostream>
using namespace std;

template<typename T, int MAXSIZE>
class Stack{
private:
    T elems[MAXSIZE];
    int numElems;
public:
    Stack();
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const {
        return numElems == 0;
    }
    bool full() const {
        return numElems == MAXSIZE;
    }
};

template<typename T, int MAXSIZE>
Stack<T, MAXSIZE>::Stack():numElems(0) {}

template<typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T const& elem)
{
    if(numElems == MAXSIZE) {
        throw out_of_range("Stack<>::push(): stack is full");
    }
    elems[numElems] = elem;
    ++numElems;
}

template<typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::pop()
{
    if(numElems <= 0) {
        throw out_of_range("Stack<>::pop(): stack is full");
    }
    --numElems;
}

template<typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::top() const
{
    if(numElems <= 0) {
        throw out_of_range("Stack<>::top(): stack is full");
    }
    return elems[numElems - 1];
}
#include<stdexcept>
#include<iostream>
using namespace std;

template<typename T, int MAXSIZE>
class Stack{
private:
    T elems[MAXSIZE];
    int numElems;
public:
    Stack();
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const {
        return numElems == 0;
    }
    bool full() const {
        return numElems == MAXSIZE;
    }
};

template<typename T, int MAXSIZE>
Stack<T, MAXSIZE>::Stack():numElems(0) {}

template<typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T const& elem)
{
    if(numElems == MAXSIZE) {
        throw out_of_range("Stack<>::push(): stack is full");
    }
    elems[numElems] = elem;
    ++numElems;
}

template<typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::pop()
{
    if(numElems <= 0) {
        throw out_of_range("Stack<>::pop(): stack is full");
    }
    --numElems;
}

template<typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::top() const
{
    if(numElems <= 0) {
        throw out_of_range("Stack<>::top(): stack is full");
    }
    return elems[numElems - 1];
}

实现代码:

#include<iostream>
#include<vector>
#include<deque>
#include<stdexcept>
#include<string>
#include<cstdlib>
#include "stack4.h"
using namespace std;

int main()
{
    try {
        Stack<int, 20> int20Stack;
        Stack<int, 40> int40Stack;
        Stack<string, 40> stringStack;

        int20Stack.push(7);
        cout<<int20Stack.top()<<endl;
        int20Stack.pop();

        stringStack.push("hello");
        cout<<stringStack.top()<<endl;
        stringStack.pop();
        stringStack.pop();
    }
    catch(exception const& ex) {
        cerr<<"Exception: "<<ex.what()<<endl;
        //return EXIT_FAILURE;
    }

    cin.get();
    return 0;
}
#include<iostream>
#include<vector>
#include<deque>
#include<stdexcept>
#include<string>
#include<cstdlib>
#include "stack4.h"
using namespace std;

int main()
{
    try {
        Stack<int, 20> int20Stack;
        Stack<int, 40> int40Stack;
        Stack<string, 40> stringStack;

        int20Stack.push(7);
        cout<<int20Stack.top()<<endl;
        int20Stack.pop();

        stringStack.push("hello");
        cout<<stringStack.top()<<endl;
        stringStack.pop();
        stringStack.pop();
    }
    catch(exception const& ex) {
        cerr<<"Exception: "<<ex.what()<<endl;
        //return EXIT_FAILURE;
    }

    cin.get();
    return 0;
}

MAXSIZE是新加入的第二个模板参数,类型为int,它指定了数组最多可包含的栈元素的个数
同样,我们可以为模板参数指定缺省值:

template<typename T = int, int MAXSIZE = 100>
class Stack {
    ...
};

  非类型的函数模板参数

你也可以为函数模板定义非类型参数。例如:

template<typename T, int VAL>
T addValue(T const& x)
{
    return x + VAL:
}

借助于STL,可以传递这个函数模板的实例化给集中的每一个元素,让他们都增加一个整数值:

std::transform(source.begin(), source.end(), dest.begin(), (int(*)(int const&))addValue<int, 5>);

  非类型模板参数的限制

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

浮点数和类对象是不允许作为非类型模板参数的:

template<double VAT>
double process(double v) //error
{
    return V * VAT;
}

template<string name>  //error
class MyClass {
    ...
};

另外,你也不能使用全局指针作为模板参数

template<char const* name>
class MyClass{
    ...
};

char const* s = "hello";
MyClass<s> x;   //s是一个指向内部连接对象的指针

但是你可以这样使用:

template<char const* name>
class MyClass {
    ...
};

extern char const s[] = "hello";
MyClass<s> x;  //OK

全局字符数组s由"hello"初始化,是一个外部链接对象

时间: 2024-10-11 23:16:42

非类型模板参数的相关文章

C++非类型模板参数

对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数.在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定.但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化. 本文地址:http://www.cnblogs.com/archimedes/p/cpp-template-type.html,转载请注明源地址. 在上篇文章(C++类模板)中我们介绍了一个stack类模

C++模板编程 - 第四章 非类型模板参数

一个例子是 1 template<typename T, int MAXSIZE> 2 class Stack {}; 在这里我就想起了C语言是怎么弄数据结构的,不得不说模板是很方便的东西.上面的例子是一个类模板,函数模板其实也是类似的. 浮点数和类对象是不允许作为非类型模板参数的. 对上面这句话的补充:这是历史原因,C++ Templates的作者认为C++在未来可能会允许使用浮点数和类对象作为非类型模板参数. 不太好理解的是这个例子 1 template<char const * n

C++标准库函数 end 的实现原理(非类型模板参数)

在刚开始学习<C++ Primer>的时候遇到了 end 函数,感觉很神奇,但又很迷惑:为什么能获得数组的尾后指针呢?编译器也不会在内存中申请一块空间放数组元素的个数啊!最近再一次遇到了 end 就看了一下它的实现终于明白了. 先说以下C语言中获得数组元素个数的方法. int arr[] = {1, 2, 3}; size_t n = sizeof(arr) / sizeof(int); //n为元素个数 sizeof 返回一个常量表达式,是在编译时期确定返回值的.也就是说在编译时期是可以知道

[013]模板-非类型模板参数

在模板中,除了定义类型参数,我们还可以定义非类型参数.例如: temlate<unsigned N, unsigned M> int foo(const char (&p1)[N], const char (&p2)[M]) { return strcmp(p1,p2); } 但是需要注意的是:编译器会在一个字符串字面常量的末尾插入一个空字符作为终结符. 例如我们调用 foo("hi", "mom"); 实际上编译器会实例化如下版本 in

读boost::multi_array有感,多维数组实现(非类型模板,偏特化)

开发环境: VS2002(VC7) 本文做如下简化: 1,假定所有维元素都是5. 2,不考虑const的[]. 3,由于只是熟悉原理,不考虑各种异常情况. 问题一,请实现一个一维整形数组,只需重载[]. 问题二,请实现一个二维整形数组,只需重载[]. 源码如下: class CIntArray1 { public: int& operator[](int index) { return m_pData[index]; } protected: int m_pData[5]; }; class C

读书笔记 effective c++ Item 44 将与模板参数无关的代码抽离出来

1. 使用模板可能导致代码膨胀 使用模板是节省时间和避免代码重用的很好的方法.你不需要手动输入20个相同的类名,每个类有15个成员函数,相反,你只需要输入一个类模板,然后让编译器来为你实例化20个特定的类和300个你需要的函数.(只有在被使用的情况下类模版的成员函数才会被隐式的实例化,所以只有在300个函数被实际用到的情况下才会生成300个成员函数.)函数模板同样吸引人.你不用手动实现许多函数,你只需要实现一个函数模板,然后让编译器来做余下的事情. 然而在有些时候,如果你不小心,使用模板会导致代

类模板参数

实际上有三种类型模板参数:类型模板参数.无类型模板参数和模板模板参数(以模板作为模板的参数). 1.类型模板参数 类型模板参数是我们使用模板的主要目的.我们可以定义多个类型模板参数: template<typename T,typename Container> class Grid {...} 同样,也可以为类型模板参数指定默认值: #include <iostream> using std::vector; template<typename T,typename Con

C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则

背景:    最近在学习C++STL,出于偶然,在C++Reference上看到了vector下的emplace_back函数,不想由此引发了一系列的“探索”,于是就有了现在这篇博文. 前言:      右值引用无疑是C++11新特性中一颗耀眼的明珠,在此基础上实现了移动语义和完美转发,三者构成了令很多C++开发者拍案叫绝的“铁三角”(当然不是所有C++开发者).而在这个“铁三角”中,有一个无法回避的关键细节,那就是引用叠加规则和模板参数类型推导规则.其实,关于这两个规则,可查到的资料不少,但都

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

 1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPushButton> #include <QLabel> template<class T> class run { public: T w; void show() { w.show(); } void settext() { w.setText("A"); }