购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.14 使用类模板参数推导简化代码

模板在C++中无处不在,但是如果总是要指定模板参数是很烦人的。在某些情况下,编译器实际上可以从上下文推导出模板参数,这个特性在C++17中可用,称为 类模板参数推导 ,它使编译器能够根据初始化列表的类型推导出缺少的模板参数。在本节中,我们将学习如何利用这个特性。

1.14.1 使用方式

在C++17中,你可以跳过指定模板参数,编译器在以下情况下可以推导出它们:

❍ 当声明变量或变量模板并初始化它时:

❍ 当使用new表达式创建对象时:

❍ 当执行类似函数的强制转换表达式时:

1.14.2 工作原理

在C++17之前,你必须在初始化变量时指定所有的模板参数,因为为了实例化类模板,所有的参数都必须是已知的,例如:

使用函数模板(例如std::make_pair())可以避免显式指定模板参数的问题,这得益于函数模板参数的推导,允许我们编写如下代码:

对于下面这个foo类模板,我们可以编写以下make_foo()函数模板来达到相同的效果:

在C++17中,对于本小节中列举的示例,我们没有必要那样做。我们可以像下面这样编写代码:

在这个上下文中,std::pair不是类型,而是作为激活类模板参数推导的类型的占位符。当编译器在声明带有初始化的变量或函数样式强制转换过程中遇到它时,会构建一组推导引导。这些推导引导是假想类类型虚构的构造函数。作为用户,你可以用用户定义的推导规则来补充这个集合,这个集合用于执行模板参数推导和重载解析。

对于下面这个std::pair例子,编译器将构建一组推导引导,其中包括以下虚构的函数模板(但不仅限于这些):

这些编译器生成的推导引导是从类模板的构造函数创建的,如果没有,则从假想的默认构造函数创建推导引导。此外,在所有情况下,假想的复制构造函数总是会创建推导引导。

用户定义的推导引导是带有尾部返回类型且没有auto关键字的函数签名(因为它们表示没有返回值的假想构造函数),它们必须定义在它们应用的类模板命名空间中。

为了理解它的工作原理,我们考虑下面这个例子,同样以std::pair对象为例:

编译器推导的类型是std::pair<int, char const*>,如果想让编译器推导std::string而不是char const*,需要用到几个用户定义的推导规则,如下所示:

这样我们就可以编写以下声明,其中字符串"demo"的类型总是被推导为std::string:

从这个例子中可以看到,推导引导不一定是函数模板。

需要注意的是,无论指定的参数有多少,如果存在模板参数列表,则不会进行类模板参数推导。例如:

因为这两个声明都指定了模板参数列表,所以它们是无效的,会导致编译错误。

1.14.3 延伸阅读

❍ 阅读1.3节,以了解花括号初始化是如何工作的。 3l9NUxFFkQjpsi++AFk5y+hicRM4/zGSC/BFYfxUT7X83nWmJaMpjFuaJh2vh6eW

点击中间区域
呼出菜单
上一章
目录
下一章
×