C++ Templates (1.4 默认模板实参 Default Template Arguments)
1.4 默认模板实参 Default Template Arguments
可以为模板参数定义默认值,这些值被称为默认模板实参(default template arguments),并且可以用于任何类型的模板[1]
比如:当需要组合不同的方法来定义返回类型使其具有不同参数类型的能力(如前一节所述),可以引入模板参数RT作为返回类型,并使RT成为两个调用实参的共同类型作为默认值。同样,有多个选择:
- 直接使用运算operator ? :。然而,由于不得不在调用参数a和b声明之前使用运算operator ? :,因此仅仅可以使用他们的类型:
basics/maxdefault1.hpp
#include <type_traits>
template <typename T1, typename T2,
typename RT = std::decay_t<decltype(true ? T1() : T2())>>
RT max(T1 a, T2 b)
{
return b < a ? a : b;
}
注意到此处使用了std::decay_t<> 用于确保不会返回引用[2]。
此实现需要传入参数的默认构造函数能够被调用。这里有另外一个解决方案,使用std::declval,但这使得声明更加复杂。第11.2.3中参考另一个例子。
- 使用类型属性中的std::common_type<>来指定返回类型的默认值:
// basics/maxdefault3.hpp
#include <type_traits>
template <typename T1, typename T2,
typename RT = std::common_type_t<T1, T2>>
RT max(T1 a, T2 b)
{
return b < a ? a : b;
}
同样请注意std::common_type<>会发生退化,因此返回值不会是一个引用。在任何情况下,调用者可以使用返回类型的默认值:
auto a = max(4, 7.2);
或者在显式指定其他模板实参类型后指定返回类型:
auto b = ::max<double, int, long double>(7.2, 4);
然而,这又有新的问题:仅仅为了指定返回类型,这需要指定3个类型。另一种替代方法需要这样一种能力:将返回类型作为第一个模板参数,但依然能够从其他模板实参中推断出该模板参数类型。理论上,前面的模板参数有默认实参而后面的模板参数没有默认实参:
template <typename RT = long, typename T1, typename T2>
RT max(T1 a, T2 b)
{
return b < a ? a : b;
}
使用该定义,可以如此调用:
int i;
long l;
...
max(i, l); // 返回long(模板参数的默认实参作为返回类型)
max<int>(4, 42); // 显式指定返回int类型
然而,这种方法只有在当模板参数具有自然的默认值的情况下才有意义(this approach only make sense, if there is a "natural" default for a template parameter)。但此处,模板参数的默认实参需要依赖于之前的模板参数。理论上,这是可能的,正如第26.5.1中所讨论的,但这依赖于类型特性,并使得定义变得复杂。
基于以上原因,最好的、最简单的解决方案便是让编译器推断返回类型,如1.3.2节所述。
脚注
C++ Templates (1.4 默认模板实参 Default Template Arguments)的更多相关文章
- C++ Templates (1.2 模板实参推断 Template Argument Deduction)
返回完整目录 目录 1.2 模板实参推断 Template Argument Deduction 1.2 模板实参推断 Template Argument Deduction 当调用函数模板(如max ...
- discuz默认模板文件结构详解-模板文件夹介绍
| — template — default 系统内置风格模板(默认风格)| — template — default – discuz_style_default.xml 风格安装文件,可用 ...
- phpcms V9 默认模板文件目录结构_PHPCms教程
PHPCMSV9 默认模板目录结构 templates 框架系统模板目录 announce 公告 show.html 内容页 ...
- django默认模板引擎和jinja2模板引擎
在使用中,大家会发现django默认模板引擎有很多局限性,最明显的就是四则运算.就只能加减,乘除都不支持.另外还有判断相等,不能直接if,要用ifequal.确实不太方便.还有一点,django默认模 ...
- eclipse - 新建jsp页面默认模板设置
有时候我们自己如果没有现成的JSP模板时,系统一般会自动生成如下页面: 这个页面显然并不是我们所需要的,所以我们需要修改默认模板 进入 修改 <%@ page language="ja ...
- grunt-init 默认模板目录更正
grunt-init是依赖grunt项目管理的脚手架工具,各种优点无须赘述,默认的template路径的作用:可以把自定义或其他模板放置其中,应用的时候直接调用模板名,不用每次寻找路径: 在安装gru ...
- Nuxt的默认模板和默认布局
Nuxt为我们提供了超简单的默认模版订制方法,只要在根目录下创建一个app.html就可以实现了 注:建立了默认模板后,记得要重启服务器,否则你的显示不会成功 默认布局主要针对于页面的统一布局使用.它 ...
- C++ Templates (2.1 类模板Stack的实现 Implementation of Class Template Stack)
返回完整目录 目录 2.1 类模板Stack的实现 Implementation of Class Template Stack 2.1.1 声明类模板 Declaration of Class Te ...
- SQL Server 默认跟踪(Default Trace)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 基础知识(Rudimentary Knowledge) 查看默认跟踪信息(Default Tr ...
随机推荐
- BUUCTF-web Easyweb
从这道题学到了挺多 一打开题目就是登陆页面,遂扫描文件检测是否存在文件泄露 用dirsearch扫出了robots.txt,.DS_Store和其他php.DS_Store没有可用信息(buuoj的题 ...
- 今天完成顺利编译d:\test\Console.java
今天完成顺利编译d:\test\Console.java import javax.swing.*;import java.awt.event.*; public class Console{ pub ...
- JAVA基础1(语法)
一.标识符和关键字 在程序中用于定义名称的都为标识符,如文件名称.类名称.方法名称或变量名称等. 在Java中标识符的定义格式由字母.数字._(下划线),$所组成,其中不能重复,不能以数字开头,不能是 ...
- Python os.open() 方法
概述 os.open() 方法用于打开一个文件,并且设置需要的打开选项,模式参数mode参数是可选的,默认为 0777.高佣联盟 www.cgewang.com 语法 open()方法语法格式如下: ...
- PHP str_ireplace() 函数
实例 把字符串 "Hello world!" 中的字符 "WORLD"(不区分大小写)替换成 "Peter": <?php高佣联盟 w ...
- 7.12 NOI模拟赛 生成树 装压dp vector装压
LINK:生成树 这场比赛我打的真失败 T3是比较容易的 却一直刚 那道"数论" 10分其实搜一下全排列. 30分容易想到对边进行装压dp. 不过存在一些细节 可以对于一个连通块的 ...
- Springboot使用JdbcTemplate的使用
在spring-boot-starter-jdbc这个依赖包中一共分成四个部分. core,JdbcTemplate等相关核心接口和类 datasource,数据源相关的辅助类 object,将基本的 ...
- org.hibernate.AssertionFailure: null id 错误
对象属性有Blob类型: 而Blob需在输入流中读取: InputStream in = new FileInputStream(url.getFile()); Blob bookPic = lobH ...
- excel-格式处理
问题[1]:将excl中数据导出txt,并且每列之间距离一个空格 在C1(任意空列) 输入=A1&" "&B1" "中间是一个半角英文空格下拉 ...
- 011_go语言中的range遍历
代码演示 package main import "fmt" func main() { nums := []int{2, 3, 4} sum := 0 for _, num := ...