住房和城乡建设厅网站首页,wordpress页面缓慢,教育网站建设的策划,互联网做网站地推2.2.2、显式实例化 有危险存在于有些类模板成员函数的编译错误#xff0c;在隐式实例化时没有注意到。未被使用的类模板成员函数也可能包含语法错误#xff0c;因为它们不会被编译到。这会使得检测代码的语法错误很困难。可以强制编译器生成所有成员函数的代码#xff0c;vi…2.2.2、显式实例化 有危险存在于有些类模板成员函数的编译错误在隐式实例化时没有注意到。未被使用的类模板成员函数也可能包含语法错误因为它们不会被编译到。这会使得检测代码的语法错误很困难。可以强制编译器生成所有成员函数的代码virtual与non-virtual通过使用explicit template instantiations。举例如下
template class Gridstring; 注意Explicit template instantiations有助于发现错误因为它们强制所有的类模板成员函数进行编译即使没有被使用。 当使用Explicit template instantiations不要只是尝试实例化类模板的基本类型比如int要用更复杂的类型比如string如果类模板支持这些类型的话。
2.2.3、类型的模板要求 当书写类型无关的代码时必须假定这些类型的特定场景。例如在Grid灯模板中假定元素类型用T代表是可被析构的copy/move可构建的copy/move可赋值的。 当编译器尝试用被调用的类模板成员函数不支持的操作实例化模板时代码编译失败错误代码通常无法辨识。然而即使想要使用的类型不支持类模板的所有成员函数要求的操作也可以开发选择性的实例化来使用一些成员函数而不是其它的。 可以使用concept来书写编译器可以解释与验证的模板参数需求。编译器可以生成更多可读的错误如果模板参数传递给不满足要求的模板实例。concept我们在本章后面讨论。
2.3、在文件之间发布模板代码 对于类模板类模板定义与成员函数定义必须在使用它们的任何源文件中对编译器可见。有几项技术可以完成这个要求。
2.3.1、成员函数定义在与类模板定义同一文件中 可以将成员函数定义直接放到定义类模板自身的模块接口文件中。当在另一个使用模板的源文件中导入这个模块时编译器具有所有需要代码的访问权限。这项技术用在了前面 Grid的实现中。
2.3.2、成员函数定义在独立的文件中 换一种方式可以将类模板成员函数定义放至独立的模块接口分区文件中。这样也需要将类模板定义放在自身的模块接口分区中。例如Grid类模板的主模块接口文件可能看起来像这样
export module grid;
export import :definition;
export import :implementation; 导入与导出两个模块接口分区:definition与implementation。类模板定义定义在了definition分区
export module grid:definition;
import std;
export template typename T class Grid { ... }; 成员函数的实现在implementation分区也需要导入definition分区因为它需要Grid类模板定义
export module grid:implementation;import :definition;
import std;export template typename T
GridT::Grid(std::size_t width, std::size_t height)
: m_width { width }, m_height { height }
{ /* ... */ }
// Remainder omitted for brevity.
2.4、模板参数 在Grid例子中Grid类模板有一个模板参数在网格中保存的类型。当书写类模板时在尖括号中指定参数如下
template typename T 该参数与函数中的参数列表类似。与函数一样可以书写想要的任意多的模板参数的类模板。还有这些参数不强制为类型可以有缺省值。
2.4.1、非类型模板参数 非类型模板参数是“正常”参数如int与指针--从函数来的比较熟悉的参数类型。然而非类型模板参数只能是整型char,int,long,等等枚举指针引用std::nullptr_t,auto,auto*,浮点型与类类型。后面这种然而会有许多限制本文不再深入讨论。记住模板在编译时实例化因此非类型模板参数在编译时验证。这意味着这样的参数必须是常量或编译时常数。 在Grid类模板中可以使用非类型模板参数来指定网格的高度与宽度而不是在构造函数中指定。使用非类型模板参数而不使用构造函数参数的主要优势是在代码编译前其值已知。回想一下在编译前通过替换模板参数编译器生成模板实例的代码。这样可以在下面的实现中使用正常的二维数组而不是使用动态改变大小的vector来进行线性表示。下面是修改之后的新的类模板定义
export
template typename T, std::size_t WIDTH, std::size_t HEIGHT
class Grid
{
public:Grid() default;virtual ~Grid() default;// Explicitly default a copy constructor and copy assignment operator.Grid(const Grid src) default;Grid operator(const Grid rhs) default;// Explicitly default a move constructor and move assignment operator.Grid(Grid src) default;Grid operator(Grid rhs) default;std::optionalT at(std::size_t x, std::size_t y);const std::optionalT at(std::size_t x, std::size_t y) const;std::size_t getHeight() const { return HEIGHT; }std::size_t getWidth() const { return WIDTH; }private:void verifyCoordinate(std::size_t x, std::size_t y) const;std::optionalT m_cells[WIDTH][HEIGHT];
}; 现在模板参数列表有三个参数了保存在网格中的对象类型网格的宽度与高度。宽度与高度用于生成二维数组保存对象。下面是类模板成员函数定义
template typename T, std::size_t WIDTH, std::size_t HEIGHT
void GridT, WIDTH, HEIGHT::verifyCoordinate(std::size_t x, std::size_t y) const
{if (x WIDTH) {throw std::out_of_range { std::format(x ({}) must be less than width ({})., x, WIDTH) };}if (y HEIGHT) {throw std::out_of_range { std::format(y ({}) must be less than height ({})., y, HEIGHT) };}
}template typename T, std::size_t WIDTH, std::size_t HEIGHT
const std::optionalT GridT, WIDTH, HEIGHT::at(std::size_t x, std::size_t y) const
{verifyCoordinate(x, y);return m_cells[x][y];
}template typename T, std::size_t WIDTH, std::size_t HEIGHT
std::optionalT GridT, WIDTH, HEIGHT::at(std::size_t x, std::size_t y)
{return const_caststd::optionalT(std::as_const(*this).at(x, y));
} 注意先前指定GridT的地方现在要指定GridT,WIDTH,HEIGHT来指定三个模板参数。
可以实例化该模板使用如下 Gridint, 10, 10 myGrid;Gridint, 10, 10 anotherGrid;myGrid.at(2, 3) 42;anotherGrid myGrid;println({}, anotherGrid.at(2, 3).value_or(0)); 代码看起来很棒但是不幸的是会有比你预期的限制更多。首先不能用非常数的整数来指定高度与宽度。下面的代码编译不成功
size_t height { 10 };
Gridint, 10, height testGrid; // DOES NOT COMPILE 如果定义height为常数编译成功
const size_t height { 10 };
Gridint, 10, height testGrid; // Compiles and works 带有正确返回类型的constexpr函数也没总是。例如如果有一个constexpr函数返回一个size_t可以用它来初始化模板的height参数
constexpr size_t getHeight() { return 10; }
...
Griddouble, 2, getHeight() myDoubleGrid; 第二个限制更要命。既然宽度与高度已经是模板参数了它们就成为了每个网格类型的一部分。这意味着Gridint,10,10与Gridint,10,11是两种不同的类型。不能将一种类型的对象赋值给另一种类型的对象也不能将一种类型的变量传递给期待另一种类型变量的函数。 注意非类型模板参数成为了实例化对象的类型规格的一部分。 文章转载自: http://www.morning.crsnb.cn.gov.cn.crsnb.cn http://www.morning.psdbf.cn.gov.cn.psdbf.cn http://www.morning.mwwnz.cn.gov.cn.mwwnz.cn http://www.morning.yrdt.cn.gov.cn.yrdt.cn http://www.morning.qrsm.cn.gov.cn.qrsm.cn http://www.morning.rwyw.cn.gov.cn.rwyw.cn http://www.morning.qxwgx.cn.gov.cn.qxwgx.cn http://www.morning.dgsr.cn.gov.cn.dgsr.cn http://www.morning.wbxr.cn.gov.cn.wbxr.cn http://www.morning.bfrsr.cn.gov.cn.bfrsr.cn http://www.morning.3dcb8231.cn.gov.cn.3dcb8231.cn http://www.morning.trrrm.cn.gov.cn.trrrm.cn http://www.morning.xkwrb.cn.gov.cn.xkwrb.cn http://www.morning.wgtnz.cn.gov.cn.wgtnz.cn http://www.morning.krgjc.cn.gov.cn.krgjc.cn http://www.morning.yrflh.cn.gov.cn.yrflh.cn http://www.morning.zycll.cn.gov.cn.zycll.cn http://www.morning.krxzl.cn.gov.cn.krxzl.cn http://www.morning.nmbbt.cn.gov.cn.nmbbt.cn http://www.morning.fktlr.cn.gov.cn.fktlr.cn http://www.morning.tgyqq.cn.gov.cn.tgyqq.cn http://www.morning.wsrcy.cn.gov.cn.wsrcy.cn http://www.morning.wfjrl.cn.gov.cn.wfjrl.cn http://www.morning.lffgs.cn.gov.cn.lffgs.cn http://www.morning.wbfly.cn.gov.cn.wbfly.cn http://www.morning.zwndt.cn.gov.cn.zwndt.cn http://www.morning.sgcdr.com.gov.cn.sgcdr.com http://www.morning.hclqy.cn.gov.cn.hclqy.cn http://www.morning.drspc.cn.gov.cn.drspc.cn http://www.morning.wrkcw.cn.gov.cn.wrkcw.cn http://www.morning.jhswp.cn.gov.cn.jhswp.cn http://www.morning.rdlxh.cn.gov.cn.rdlxh.cn http://www.morning.gxhqt.cn.gov.cn.gxhqt.cn http://www.morning.ngcth.cn.gov.cn.ngcth.cn http://www.morning.ntgrn.cn.gov.cn.ntgrn.cn http://www.morning.prxqd.cn.gov.cn.prxqd.cn http://www.morning.tqldj.cn.gov.cn.tqldj.cn http://www.morning.lznqb.cn.gov.cn.lznqb.cn http://www.morning.taipinghl.cn.gov.cn.taipinghl.cn http://www.morning.zlchy.cn.gov.cn.zlchy.cn http://www.morning.clpfd.cn.gov.cn.clpfd.cn http://www.morning.lrjtx.cn.gov.cn.lrjtx.cn http://www.morning.fxzw.cn.gov.cn.fxzw.cn http://www.morning.rlqml.cn.gov.cn.rlqml.cn http://www.morning.rxpp.cn.gov.cn.rxpp.cn http://www.morning.lgxzj.cn.gov.cn.lgxzj.cn http://www.morning.yfnhg.cn.gov.cn.yfnhg.cn http://www.morning.plkrl.cn.gov.cn.plkrl.cn http://www.morning.wnkjb.cn.gov.cn.wnkjb.cn http://www.morning.znlhc.cn.gov.cn.znlhc.cn http://www.morning.hsjfs.cn.gov.cn.hsjfs.cn http://www.morning.bnrnb.cn.gov.cn.bnrnb.cn http://www.morning.kmcfw.cn.gov.cn.kmcfw.cn http://www.morning.jtqxs.cn.gov.cn.jtqxs.cn http://www.morning.hphqy.cn.gov.cn.hphqy.cn http://www.morning.iznek.com.gov.cn.iznek.com http://www.morning.nnrqg.cn.gov.cn.nnrqg.cn http://www.morning.gtkyr.cn.gov.cn.gtkyr.cn http://www.morning.pzcqz.cn.gov.cn.pzcqz.cn http://www.morning.fhwfk.cn.gov.cn.fhwfk.cn http://www.morning.lwwnq.cn.gov.cn.lwwnq.cn http://www.morning.scrnt.cn.gov.cn.scrnt.cn http://www.morning.lsfrc.cn.gov.cn.lsfrc.cn http://www.morning.xqcst.cn.gov.cn.xqcst.cn http://www.morning.fhrt.cn.gov.cn.fhrt.cn http://www.morning.hctgn.cn.gov.cn.hctgn.cn http://www.morning.zzfjh.cn.gov.cn.zzfjh.cn http://www.morning.dbsch.cn.gov.cn.dbsch.cn http://www.morning.qggm.cn.gov.cn.qggm.cn http://www.morning.ychrn.cn.gov.cn.ychrn.cn http://www.morning.pdkht.cn.gov.cn.pdkht.cn http://www.morning.llllcc.com.gov.cn.llllcc.com http://www.morning.yckwt.cn.gov.cn.yckwt.cn http://www.morning.gllhx.cn.gov.cn.gllhx.cn http://www.morning.kwwkm.cn.gov.cn.kwwkm.cn http://www.morning.kybjr.cn.gov.cn.kybjr.cn http://www.morning.xznrk.cn.gov.cn.xznrk.cn http://www.morning.hrjrt.cn.gov.cn.hrjrt.cn http://www.morning.cyyhy.cn.gov.cn.cyyhy.cn http://www.morning.bqhlp.cn.gov.cn.bqhlp.cn