惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
月光博客
月光博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 聂微东
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
美团技术团队
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
A
About on SuperTechFans
Jina AI
Jina AI
D
Docker
Last Week in AI
Last Week in AI
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率
C++ 模板系列小结02-非类型模板参数
音视频开发进阶 · 2021-02-08 · via 音视频开发进阶

一个专注音视频领域的小圈子

前面已经介绍了函数模板和类模板,还介绍了类模板的默认参数,在代码示例中都是用具体类型来作为模板参数的。 实际上,模板参数不局限于类型,普通值也可以作为模板参数,也就是本篇要讲的内容:非类型模板参数。

非类型模板参数

非类型模板参数的使用和类型模板参数有些不一样,不需要 typename 关键字了,直接指定具体类型。

如下代码所示:

template<typename T, int MAXSIZE = 20>
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(const T &elem) {
    if (numElems == MAXSIZE) {
        throw std::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 std::out_of_range("Stack<>::pop(): empty stack");
    }
    numElems--;
}

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

int main() {
    STACK<int> intStack;
    intStack.push(1);
    intStack.top();
    intStack.pop();

    STACK<int,10> int10Stack;
    int10Stack.push(1);
    int10Stack.top();
    int10Stack.pop();
    return 0;
}

在使用非类型模板参数的时候,也就是基于值的模板参数,要么显示地指定这些值,要么作为默认参数有默认值。

非类型的函数模板参数

除了上面的类模板,函数模板同样可以用非类型的模板参数。

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

int main{
    addValue(10);
    return 0;
}

可以看到函数模板同样是可以用默认参数值的。

非类型模板参数的限制

不是所有的类型都可以作为非类型模板参数,它是有限制的。

通常而言,只有常整数(包括枚举值)或者指向外包链接对象的指针 才可以,而浮点数和类对象是不允许作为非类型模板参数的。

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

以上的代码示例就是不行的。

小结

非类型模板参数只是 C++ 模板知识点里面一个小方面了,但在某些场景还在能发挥大作用的。

原创文章,转载请注明来源:    C++ 模板系列小结02-非类型模板参数