C++ 模板浅谈

引言与概述

C++模板机制允许在定义类,函数,类型别名的时候将类型或值当作参数,这样定义的类和函数在运行时间和空间效率上并不逊色于手工打造的非通用的代码。

模板提供的代码是类型安全的。

模板是一种编译时期的机制,与手工编写的代码相比,并不会产生任何运行期开销。

对模板来说,只有当一个成员函数被使用时才会被生成代码。

一个通用的组件应该从一个或多个具体实例泛化而来,而不是简单的从第一原理直接而来。 即我们可以先写一个具体的函数或者类,然后改成泛化类型。

模板简介

一个简单的模板

template <typename C>
class String {
public:String();explicit String(const C* c);//.....
private:static const int short_max = 15;//用于短字符串的优化int sz;C* ptr;
};

一个模板类的声明与普通class的声明差别不大,只需要添加关键字和将需要泛化的类型进行替换。

模板成员函数也可以不用定义在类内,也可以在外部定义,但模板成员函数本身还是一个模板,所以要显式声明一个模板:

template<typename C>
String<C>::String()sz(0),ptr(nullptr)
{}

模板实例化

模板实例化:从一个模板和一个模板实参列表生成一个类或者一个函数的过程。

{String<char> str;
}

即可以进行变量的声明,注意这里我们只创建了对象,即这个类型String< char > 编译器会为其生成默认构造函数和析构函数,不使用的成员对象或者函数则不会生成。

模板提供了一种用少量代码来生成大量代码的机制,但我们要小心实例代码的泛滥,造成内存的大量占用。
通过组合模板和简单内联可以消除很多直接或者间接函数调用的开销。

模板参数

模板机制的最大弱点是无法直接表达对模板参数的要求。

template <Container Cont, typename Elem>requires Equal_comparable<Cont::value_type, Elem>()
int find_index(Cont& c, Elem e);

但我们可以这写来进行模板参数的检查。
在C++20 出现了concept这种技术,可以帮助我们进行对模板参数要求的检查。

但这种检查是在编译过程中非常晚的时刻进行的,而且是在抽象层次很低的层次上运行的,帮助有限。

成员类型别名

如果我们想要在类外使用模板参数,目前只有使用成员类型别名这种方法:

template <typename C>
class String {
public:using value_type = T;
};

static成员

一个static的成员只有被真正使用时才被定义。

template <typename T>
struct X
{static int a;static int b;
};
int* p = &X<int>::a;

如果这就是全部代码,那么 a 会被报错为无定意,而b就不会。

模板与virtual

模板成员函数不能是虚函数,如果使用那么为虚函数实现的传统技巧虚表就很难使用,并且链接器的复杂性也会很高。

模板与嵌入类型

在模板中尽量避免嵌入类型,除非它们真正依赖所有的模板参数。

模板与友元

template <typename T>
class B;template <typename T>
void A(const B<T>& b);template <typename T>
class B {
public:friend void A<>(const B<T>& b);
};

友元后面的<>是必须的,它指明了友元是一个模板函数,如果没有<>,则友元函数被假定为非模板函数。友元函数只有被使用时才会被实例化。

友元的设计目的是为了表达一小群紧密相关的概念,如果友元关系很复杂,那么一定是一个设计错误。

源码组织

使用模板组织源码有三种很明显的方法:

  • 在一个编译单元中,在使用模板前包含其定义;
  • 在一个编译单元中,在使用模板前(只)包含其声明。在模板稍后的位置(或者使用之后)包含模板定义;
  • 在一个编译单元中,在使用模板前(只)包含其声明。在其他编译单元中包含其定义。

很遗憾的是C++并不支持第三种实现方式。

如果一个类模板的布局或者是一个内联函数模板的定义发生了改变,那么使用该类或者该函数的代码都要重新编译。

建议

  1. 使用模板用于很多实参类型的算法
  2. 用模板表示容器
  3. 注意template < class T>和template < typename T>意义相同
  4. 当设计一个模板时,首先设计和调试非模板版本,随后添加参数将其泛化
  5. 模板是类型安全的,但检查的时机太晚了
  6. 当设计一个模板时,仔细思考concept,它对模板参数的要求
  7. 如果一个类模板必须是可拷贝的,则为它定义一个非模板的拷贝构造函数和拷贝复制运算符
  8. 如果一个类模板必须是可移动的,则为它定义一个非模板的移动构造函数和移动复制运算符
  9. 虚函数不能是成员模板函数
  10. 只有当一个类型,依赖类模板的所有实参时才将其定义为模板成员
  11. 使用函数模板推断类模板实参类型
  12. 对多种不同的实参类型,重载函数模板来获得相同语义
  13. 借助实参带入失败机制为程序提供正确的候选函数集
  14. 使用模板别名简化符号,隐藏实现细节
  15. C++不支持模板分别编译,在每个用到模板的编译单元中都#include模板定义
  16. 使用普通函数作为接口编不能用模板处理的代码
  17. 将大的模板和较严重依赖上下文的模板分开编译

没事的,不论未来如何,太阳一定都会升起!没事的,不论未来如何,太阳一定都会升起!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246294.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPU Gems1 - 18 空间BRDF(Spatial BRDFs)

这章主要介绍了空间双向反射分布函数&#xff08;SBRDF&#xff09;&#xff0c;接着文章讨论了压缩SBRDF表达式&#xff0c;以及由离散光或环境贴图所照明的SBRDF的渲染方法。关于BRDF请参考大佬浅墨的这篇文章https://blog.csdn.net/poem_qianmo/article/details/75943714 S…

浅谈表面反射——波动光学篇

Radiometric Definitions 首先让我们来回忆一下辐射度量学中关于irradiance和radiance的定义&#xff1a; 我们在这里定义光源(source)在x-z平面&#xff0c;因此入射光就可以只用θi\theta_{i}θi​来描述。dAs\mathrm{d}A_{s}dAs​是表面积。定义dΦi\mathrm{d}\Phi_{i}dΦ…

GPU Gems1 - 19 基于图像的光照(Image-Based Lighting)

这篇文章打破了当时立方体贴图环境&#xff08;Cube-Map Environment&#xff09;用法的桎梏&#xff0c;深入研究了更多可能的逼真光照效果。文章主要研究了基于图像的光照&#xff08;Image-Based Lighting&#xff0c;IBL&#xff09;&#xff0c;包括局部化的立方体映射&am…

Polygonal-Light Shading with LTC

概述 如果我们有一个上半球的余弦分布函数(Do)(D_{o})(Do​)&#xff0c;并对这个余弦分布函数进行一个矩阵(M)(M)(M)变换&#xff0c;变换为一个新的分布函数(D)(D)(D)。 DMDoD M D_{o}DMDo​ 这就是基本思想&#xff1a;用一个余弦分布函数来拟合出不同的分布函数&#xff…

GPU Gems1 - 20 纹理爆炸(Texture Bombing)

【章节概览】 这章介绍了纹理爆炸&#xff08;Texture Bombing&#xff09;和相关的细胞技术&#xff0c;它们能在Shader中增加视觉的丰富性&#xff0c;图像的多样性&#xff0c;并减少大块纹理图案的重复性。 【核心要点】 纹理爆炸&#xff08;Texture bombing&#xff0…

Catlike Coding网站文章解析 -- 1.Procedural Grid

原文英文版链接https://catlikecoding.com/unity/tutorials/procedural-grid/&#xff0c;里面有每一部分的untiy工程链接&#xff0c;文章内容也更详实。 本章内容&#xff1a; 创建一系列点使用协程实现他们的摆放位置定义一个由三角形组成的平面自动生成法线添加纹理坐标和…

GPU Gems1 - 21 实时辉光(Real-Time Glow)

这章浅墨的文章讲的很细了&#xff0c;这里基本照扒一遍加深印象&#xff0c;原文链接&#xff1a;https://zhuanlan.zhihu.com/p/36499291 【章节概览】 这章讲到2D光照效果中的辉光&#xff08;Glow&#xff09;和光晕&#xff08;Halo&#xff09;&#xff0c;展示了如何通…

Catlike Coding网站文章解析 -- 2.Procedural Grid

本章内容 创建一个闭合的cube mesh给cube添加带弧度平滑的边缘定义法线使用sub-meshes&#xff08;子mesh&#xff09;创建一个常规shader合并碰撞体1.合成一个cube 上一章https://mp.csdn.net/postedit/89474068我们已经实现了一个平面mesh。一个cube由6个平面组成&#xff…

GPU Gems1 - 23 景深技术综述

本章主要介绍如何使用GPU创建实时的景深&#xff08;Depth of Field&#xff09;效果。参考浅墨总结文章的链接https://zhuanlan.zhihu.com/p/36499291 聚焦在枪上&#xff0c;背景模糊【核心要点】 物体在距离镜头的一个范围之内能够清晰成像&#xff08;经过聚焦&#xff09…

GPU Gems1 - 22 颜色控制(Color Controls)

这章将在游戏中图像处理的讨论&#xff0c;扩展到技术和艺术上控制颜色的方法和应用&#xff0c;包括将图像从一些的色彩空间中移入移出&#xff0c;以及快速地给任何2D或3D场景加上精美的色调。 色彩校正&#xff08;Color Correction&#xff09;是几乎所有印刷和胶片成像应…

GPU Gems1 - 25 用纹理贴图进行快速过滤宽度的计算

这章介绍在片元shader中计算导数近似值的技术。这个技术把特别的值载入纹理mipmap的每个级别&#xff0c;以特殊的方式使用纹理映射硬件&#xff0c;计算出导数的结果&#xff0c;给出在屏幕上的像素间某个量的变化率。 Cg标准程序库提供ddx和ddy函数&#xff0c;计算任意关于…

c#基础知识(1)

简介&#xff1a;C# 是一个现代的、通用的、面向对象的编程语言&#xff0c;它是由微软&#xff08;Microsoft&#xff09;开发的&#xff0c;由 Ecma 和 ISO 核准认可的。 程序结构&#xff1a;引用命名空间、命名空间、类、方法、属性、语句。 数据类型&#xff1a;bool、byt…

GPU Gems1 - 24 高质量的过滤

在一些应用中&#xff0c;高质量的过滤是至关重要的&#xff0c;可以用像素shader代码执行任何过滤。GPU着色程序不用于CPU的主要之处在于&#xff1a;一般来说&#xff0c;CPU数学操作比纹理访问更快&#xff0c;而在GPU中恰恰相反。图像过滤的目的很简单&#xff1a;对于给你…

2021-04-05

见缝插针小游戏 结束动画 我们的结束动画很简单&#xff0c;就是把画面放大&#xff0c;把背景改成红色&#xff0c;再有一个停顿就可以了 1、对于放大画面和修改背景颜色的操作&#xff0c;在这里可以直接修改相机设置 我们要获取到Hierarchy窗口中的Main Camera&#xff0c;…

GPU Gems1 - 26 OpenEXR图像文件格式与HDR(The OpenEXR Image File Format and HDR)

【章节概览】 这章中&#xff0c;大名鼎鼎的工业光魔公司的Florian Kainz、Rod Bogart和DrweHess介绍了OpenEXR标准&#xff0c;这是一种当时新的高动态范围图像&#xff08;HDRI&#xff09;格式&#xff0c;在计算机成像的顶级电影中正在快速推广。对于基于图像照明的开发者…

2021-04-08

unity入门教程 创建开始界面 在场景中创建画布Canvas&#xff0c;然后制作开始界面。 首先在Canvas下新建一个空物体&#xff0c;命名为StartWnd。然后在StartWnd下新建一个Image&#xff0c;命名为imgTitle&#xff0c;SourceImage使用main图片。然后在StartWnd下新建一个Butt…

ID Tech 5 中Megatexture针对地形的D3D9 基本实现原理

看GPU Gems2中的 使用基于GPU几何体裁剪图的地形渲染&#xff08;Terrain Rendering Using GPU-Based Geometry Clipmaps&#xff09;一文&#xff0c;对Clipmap技术不是理解很好&#xff0c;所以上网搜索一番&#xff0c;发现了这篇文章&#xff0c;实在是太棒的文章&#xff…

2021-04-12

异步传输&#xff08;Asynchronous Transmission&#xff09;&#xff1a;异步传输模式(Asynchronous Transfer Mode,缩略语为ATM) 异步传输一般以字符为单位&#xff0c; 起始位&#xff1a;先发出一个逻辑”0”信号&#xff0c;表示传输字符的开始。 空闲位&#xff1a;处于逻…

[知乎] 开放世界游戏中的大地图背后有哪些实现技术?

今天看到的一篇关于大世界的技术文章&#xff0c;写的太好了&#xff0c;膜拜大佬。各位如果有时间一定要看看 原文&#xff1a;http://gulu-dev.com/post/2014-11-16-open-world#toc_10 一、程序技术篇&#xff1a;算法和架构&#xff08;Programming Algorithms & Arch…

角色控制器

一、简介 角色控制器(Character Controller)主要用于对第三人称或第一人称游戏主角的控制。 二、基本概念 第三人称游戏中的这些控制器由于无规律可循&#xff0c;所以无法遵守固定的物理规则&#xff0c;例如&#xff0c;让某辆车每小时跑 90 英里&#xff0c;但是它可能会突…