深化探求模板编程的精华-从类型参数到智能推导-模板的艺术-C-把握 (深化探求模板范文)
类型模板参数
在示例中,模板有一个模板参数:存储在网格中的类型。编写类模板时,您须要在尖括号内指定参数列表,例如:
这个参数列表相似于函数或方法中的参数列表。与函数和方法一样,你可以编写具备恣意多个模板参数的类。此外,这些参数不用是类型,它们可以有自动值。
非类型模板参数
非类型参数是个别参数,如整数和指针——这类参数你或者曾经在函数和方法中很相熟了。但是,非类型模板参数只能是整型(、、等)、枚举类型、指针、援用、
std::nullptr_t
、、和。C++20还准许浮点类型和类类型的非类型模板参数。后者有很多限度,在本文中不再具体讨论。
在类模板中,你可以经常使用非类型模板参数来指定网格的高度和宽度,而不是在结构函数中指定。在模板列表中指定非类型参数而不是在结构函数中指定的关键好处是这些值在代码编译之前就已知。回顾一下,编译器经过在编译之前交流模板参数来生成模板实例的代码。因此,你可以在成功中经常使用个别的二维数组,而不是灵活调整大小的向量数组。以下是带有更改的新类定义:
exporttemplate<typenameT,size_tWIDTH,size_tHEIGHT>classGrid{public:Grid()=default;virtual~Grid()=default;//明白自动复制结构函数和赋值运算符。Grid(constGrid&src)=default;Grid&operator=(constGrid&rhs)=default;std::optional<T>&at(size_tx,size_ty);conststd::optional<T>&at(size_tx,size_ty)const;size_tgetHeight()const{returnHEIGHT;}size_tgetWidth()const{returnWIDTH;}private:voidverifyCoordinate(size_tx,size_ty)const;std::optional<T>m_cells[WIDTH][HEIGHT];};
留意,模板参数列表须要三个参数:存储在网格中的对象类型,以及网格的宽度和高度。宽度和高度用于创立存储对象的二维数组。上方是类方法的定义:
//类方法定义template<typenameT,size_tWIDTH,size_tHEIGHT>voidGrid<T,WIDTH,HEIGHT>::verifyCoordinate(size_tx,size_ty)const{if(x>=WIDTH){throwstd::out_of_range{std::format("{}mustbelessthan{}.",x,WIDTH)};}if(y>=HEIGHT){throwstd::out_of_range{std::format("{}mustbelessthan{}.",y,HEIGHT)};}}template<typenameT,size_tWIDTH,size_tHEIGHT>conststd::optional<T>&Grid<T,WIDTH,HEIGHT>::at(size_tx,size_ty)const{verifyCoordinate(x,y);returnm_cells[x][y];}template<typenameT,size_tWIDTH,size_tHEIGHT>std::optional<T>&Grid<T,WIDTH,HEIGHT>::at(size_tx,size_ty){returnconst_cast<std::optional<T>&>(std::as_const(*this).at(x,y));}
留意,之前你在哪里指定了,如今你必定指定来指定三个模板参数。你可以这样实例化并经常使用这个模板:
Grid<int,10,10>myGrid;Grid<int,10,10>anotherGrid;myGrid.at(2,3)=42;anotherGrid=myGrid;cout<<anotherGrid.at(2,3).value_or(0);
这段代码看起来很棒,但可怜的是,存在比你最后预期的更多限度。首先,你不能经常使用十分量整数来指定高度或宽度。以下代码无法编译:
size_theight{10};Grid<int,10,height>testGrid;//无法编译
但是,假设你将高度定义为常量,则可以编译:
constsize_theight{10};Grid<int,10,height>testGrid;//可编译并上班
具备正确前往类型的函数也可以上班。例如,假设你有一个前往的函数,你可以用它来初始化高度模板参数:
constexprsize_tgetHeight(){return10;}...Grid<double,2,getHeight()>myDoubleGrid;
第二个限度或者更关键。如今宽度和高度是模板参数,它们是每个网格类型的一局部。这象征着和是两种不同的类型。你不能将一种类型的对象赋值给另一种类型的对象,也不能将一种类型的变量传递给希冀另一种类型变量的函数或方法。
类模板参数的自动值
设置高度和宽度的自动值
假设您继续经常使用高度和宽度作为模板参数的方法,您或者想为类结构函数中之前的高度和宽度非类型模板参数提供自动值。C++准许您经常使用相似的语法为模板参数提供自动值。同时,您也可认为类型参数提供自动值。上方是类定义:
exporttemplate<typenameT=int,size_tWIDTH=10,size_tHEIGHT=10>classGrid{//其他局部与之前版本相反};
在方法定义的模板规范中,您不须要为、和指定自动值。例如,这是方法的成功:
template<typenameT,size_tWIDTH,size_tHEIGHT>conststd::optional<T>&Grid<T,WIDTH,HEIGHT>::at(size_tx,size_ty)const{verifyCoordinate(x,y);returnm_cells[x][y];}
如今,您可以在没有任何模板参数的状况下实例化,只要指定元素类型,元素类型和宽度,或元素类型、宽度和高度:
Grid<>myIntGrid;Grid<int>myGrid;Grid<int,5>anotherGrid;Grid<int,5,5>aFourthGrid;
请留意,假设您不指定任何类模板参数,您依然须要指定一组空的尖括号。例如,以下代码无法编译!
GridmyIntGrid;
类模板参数列表中自动参数的规定与函数或方法相反;也就是说,您可以从左边开局为参数提供自动值。
类模板参数推导(CTAD)
智能推导模板参数
类模板参数推导准许编译器智能从传递给类模板结构函数的参数推导出模板参数。例如,规范库中有一个名为的类模板,在中定义,并在第1章中引见。存储两个或者不同类型的值,通常须要指定为模板参数。例如:
pair<int,double>pair1{1,2.3};
为了防止编写模板参数,可以经常使用一个名为
std::make_pair()
的辅佐函数模板。编写自己的函数模板的细节将在本章前面讨论。函数模板不时支持基于传递给函数模板的参数智能推导模板参数。因此,
make_pair()
能够依据传递给它的值智能推导出模板类型参数。例如,编译器为以下调用推导出:
autopair2{make_pair(1,2.3)};
经常使用类模板参数推导(CTAD),不再须要这样的辅佐函数模板。编译器如今会依据传递给结构函数的参数智能推导出模板类型参数。关于类模板,您可以方便地编写以下代码:
pairpair3{1,2.3};//pair3的类型为pair<int,double>
当然,这仅在类模板的一切模板参数要么具备自动值,要么用作结构函数中的参数,从而可以推导进去时才有效。请留意,CTAD要求有一个初始化器能力上班。以下是合法的:
pairpair4;
许多规范库类支持CTAD,例如、等。
用户定义的推导指南
您也可以编写自己的用户定义推导指南来协助编译器。这些指南准许您编写模板参数如何被推导的规定。这是一个初级主题,所以不会具体讨论,但会给出一个示例来展现它们的弱小配置。假定您有以下
SpreadsheetCell
类模板:
template<typenameT>classSpreadsheetCell{public:SpreadsheetCell(Tt):m_content{move(t)}{}constT&getContent()const{returnm_content;}private:Tm_content;};
经常使用智能模板参数推导,您可以创立一个
std::string
类型的
SpreadsheetCell
:
stringmyString{"HelloWorld!"};SpreadsheetCellcell{myString};
但是,假设您将
constchar*
传递给
SpreadsheetCell
结构函数,则类型被推导为
constchar*
,这不是您想要的!您可以创立以下用户定义的推导指南,当向结构函数传递
constchar*
作为参数时,使其将推导为
std::string
:
SpreadsheetCell(constchar*)->SpreadsheetCell<std::string>;
这个指南必定在类定义
之外但在与
SpreadsheetCell
类相反的命名空间内定义。通用语法如下。关键字是可选的,其行为与结构函数的相反。通常,这样的推导指南也是模板。
explicitTemplateName(Parameters)->DeducedTemplate;
请C++高手指导 IntelliSense: 缺少 类模板 "std::iterator" 的参数列表 。如何添加类模板到集成环境
std::vector<char>::iterator q;//char替换成你需要的参数类型,q替换成你的迭代器名,不在前面在using,写在main函数前面,试试看
新手如何学习编程?
学编程入门建议:1.学编程要从根本出发,从理论上来说,需要广泛的阅读。 了解算法的博大精深和计算机的基本理论。 2.从实践上来说,需要有广泛的练习,练习的广泛在于练习不同的内容。 然后就是创新精神和数学思维能力,这些都是需要培养的。 基础要打好学编程要具备一定的基础。 3.逻辑思维能力的培养、学程序设计要有一定的逻辑思维能力。 “思维能力”的培养要长时间的实践锻炼。 要想成为一名优秀的程序员,最重要的是掌握编程思想。 要做到这一点必须在反复的实践、观察、分析、比较、总结中逐渐地积累。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。