模板显式特化与隐式特化

当使用一个模板时,称为实例化模板。模板实例是编译器通过将模板参数应用于模板定义而创建的具体函数或类。模板实例又称为特化。因此,rational<int>是模板rational<>的一个特化。因此,特化是针对特定一组模板参数实现模板的过程。
C++允许为一个特定的模板参数集合定义一个定制的特化;也就是说,可以创建一个规则的例外情况。当你自己定义特化而不是让编译器为你实例化模板时,它被称为显式特化(也称为完全特化)。编译器自动创建的特化将是隐式特化。

使用template<>开始一个显式特化的声明,告诉编译器正在编写一个显式特化,接下来是定义。注意类名是特化模板名称(例如Point<int>),让编译器知道正在特化什么。在可以特化一个模板之前,必须告诉编译器类模板(即原始模板)的定义。通常,会在一个单独的头文件中先写类模板声明,后跟它的特化。
显式特化完全取代了模板参数的模板声明(如果模板接受多个参数,则必须为每个参数提供一个特定的值)。尽管惯例规定Point<int>应该定义与主模板Point<>相同的所有成员,但编译器并不强制执行此类限制。也就是说特化版本的具体实现可以与原始模板不同。

#include <iostream>
#include <vector>template<class T>
class Point{
public:Point(T x, T y):x_(x), y_(y){std::cout << __PRETTY_FUNCTION__ << std::endl;}Point(const Point& pt): x_(pt.x_), y_(pt.y_){std::cout << __PRETTY_FUNCTION__ << std::endl;}Point& operator=(const Point& pt)& {Point(pt.x_, pt.y_).swap(static_cast<Point&>(*this));std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}Point(Point&& pt) noexcept: x_(pt.x_), y_(pt.y_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Point& operator=(Point&& pt)& noexcept{x_ = pt.x_;y_ = pt.y_;std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}void swap(Point& pt) noexcept{std::swap(x_, pt.x_);std::swap(y_, pt.y_);std::cout << __PRETTY_FUNCTION__ << std::endl;}virtual ~Point(){std::cout << __PRETTY_FUNCTION__ << std::endl;}T getX()const{return x_;}T getY()const{return y_;}void moveTo(T x, T y);/*【类内又有模板】方式一,在类内声明,在类外定义 */template<class U>U ratio() ;/*【类内又有模板】方式二,在类内定义 */template<class V>V multiply() {return static_cast<V>(x_) * static_cast<V>(y_);}private:T x_;T y_;
};template<class T>
void Point<T>::moveTo(T x, T y){x_ = x;y_ = y;
}template<class T>
template<class U>
U Point<T>::ratio() {return static_cast<U>(x_) / static_cast<U>(y_); // omit devided by zero.
}template<>
class Point<int>{
public:Point(int x, int y):x_(x), y_(y){std::cout << __PRETTY_FUNCTION__ << std::endl;}Point(const Point& pt): x_(pt.x_), y_(pt.y_){std::cout << __PRETTY_FUNCTION__ << std::endl;}Point& operator=(const Point& pt)& {Point(pt.x_, pt.y_).swap(static_cast<Point&>(*this));std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}Point(Point&& pt) noexcept: x_(pt.x_), y_(pt.y_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Point& operator=(Point&& pt)& noexcept{x_ = pt.x_;y_ = pt.y_;std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}void swap(Point& pt) noexcept{std::swap(x_, pt.x_);std::swap(y_, pt.y_);std::cout << __PRETTY_FUNCTION__ << std::endl;}virtual ~Point(){std::cout << __PRETTY_FUNCTION__ << std::endl;}int getX()const{return x_;}int getY()const{return y_;}void moveTo(int x, int y){x_ = x;y_ = y;}double ratio(){std::cout << "Specialized version of type int.\n";return static_cast<double>(x_) / static_cast<double>(y_); // omit devided by zero.}double multiply() {return static_cast<double>(x_) * static_cast<double>(y_);}private:int x_;int y_;
};int main() {Point<int> pt1(1, 2);Point<float> pt2(2.3f, 4.5f);Point<double> pt3(2.3, 4.5);pt1.ratio();pt2.ratio<double>();
}

输出:

Point<int>::Point(int, int)
Point<T>::Point(T, T) [with T = float]
Point<T>::Point(T, T) [with T = double]
Specialized version of type int.
Point<T>::~Point() [with T = double]
Point<T>::~Point() [with T = float]
virtual Point<int>::~Point()

由输出可以看出int版用的是特化版本,而且 double ratio()的实现与原始模板也不同(输出了Specialized version of type int.)。

Reference

Exploring C++ 11, 2nd Edition.

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

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

相关文章

linux部署java1.8(jdk1.8)

两种方式&#xff1a; 方式一 1.输入查找命令&#xff1a; yum -y list java*2.输入安装命令&#xff1a; yum install -y java-1.8.0-openjdk.x86_643.测试是否已经安装&#xff1a; java -version方式二&#xff1a; 点击链接进入官网&#xff1a;https://www.oracle.com/…

Python 全栈体系【四阶】(四十一)

第五章 深度学习 九、图像分割 1. 基本介绍 1.1 什么是图像分割 图像分割&#xff08;Segmentation&#xff09;是图像处理和机器视觉一个重要分支&#xff0c;其目标是精确理解图像场景与内容。图像分割是在像素级别上的分类&#xff0c;属于同一类的像素都要被归为一类&a…

ReactFlow的ReactFlow实例事件传参undefined处理状态切换

1.问题 ReactFlow的ReactFlow实例有些事件我们在不同的状态下并不需要&#xff0c;而且有时候传参会出现其它渲染效果&#xff0c;比如只读状态下我们不想要拖拉拽onEdgesChange连线重连或删除的功能。 2.思路 事件名称类型默认值onEdgesChange(changes: EdgeChange[]) >…

pandas快速使用

DataFrame介绍 Dateframe结构和列表类似&#xff0c;区别是对于DataFrame的每一列和每一行均有一个标签。例如以下数据&#xff0c; 上述数据中&#xff0c;日期作为每行的标签。a、b、c、d、e分别是每列的标签 生成连续日期数据 使用方法date_range()&#xff0c;该方法有两…

MySQL部署系列-centos离线安装MySQL

MySQL部署系列-centos离线安装MySQL 文章目录 MySQL部署系列-centos离线安装MySQL1. 查看是否已经安装 Mysql3. 下载官方 Mysql 包3. 下载之后上传到服务器4. 创建用户组5. 创建数据目录并赋予权限6. 修改配置文件 vim /etc/my.cnf7. 初始化数据库(数据库安装)8. 加入到系统服务…

【3dmax笔记】035: 车削修改器

一、车削修改器介绍 车削&#xff1a;图形通过绕轴旋转来创建三维效果。 开放的样条线&#xff0c;车削之后是面片。闭合的样条线&#xff0c;车削之后&#xff0c;是实体。 一、车削修改器实例 绘制高脚杯&#xff0c;首先在前视图绘制如下二维图形。 添加一个车削的修改器…

(六)JSP教程——out对象

out对象是在JSP中经常使用到的对象&#xff0c;它本质上是一个输出流&#xff0c;前面已经多次使用&#xff0c;我们经常使用它的print()和println()方法&#xff0c;这些方法主要用于实现客户端数据的输出。通过out对象也可以直接向客户端发送一个由程序动态生成的HTML文件。 …

PackageKit使用(二)

本篇主要讲述&#xff0c;如何调用PackageKit c库的接口&#xff0c;只举例个别接口&#xff0c;基本上通用。 //检测更新 auto refresher PackageKit::Daemon::refreshCache(false);connect(refresher, &PackageKit::Transaction::errorCode, this, &MainWindow::er…

关于YOLO8学习(三)训练自定义的数据集

前文 关于YOLO8学习(一)环境搭建,官方检测模型部署到手机 关于YOLO8学习(二)数据集收集,处理 简介 本文将会讲解: (1)如何通过PyCharm,进行训练数据,实现人脸检测 开发环境 win10、python 3.11、cmake、pytorch2.0.1+cu117、pycharm、ultralytics==8.0.134 要特…

计算机网络 3.2网络体系结构

第二节 网络体系结构 一、网络协议 1.定义&#xff1a; ①通信双方共同遵守的规则。 ②为网络数据交换制定的规则、约定与标准。 ③网络实体之间通信时有关信息传输顺序、信息格式、信息内容的约定或规则。 2.协议三要素&#xff1a; 语法&#xff1a;确定协议元素的格式…

电子邮件协议

目录 概述 电子邮件系统 客户端 服务器 MIME规范 MIME类型 MIME编码 SMTP协议 SMTP命令和响应 SMTP认证 POP协议 POP连接过程 POP模式 IMAP协议 IMAP连接过程 IMAP模式 总结 概述 电子邮件是互联网时代最常用的通信方式之一&#xff0c;它允许人们在世界各地快…

Double 4 VR智能互动情景教学系统在商务英语课堂中的应用

随着科技的不断发展&#xff0c;虚拟现实技术&#xff08;VR&#xff09;已经逐渐渗透到教育领域&#xff0c;为课堂教学带来了新的可能性。商务英语课堂也不例外&#xff0c;VR智能互动情景教学系统在商务英语课堂中的应用&#xff0c;能够为学生提供更加真实、生动的商务场景…

大模型和传统ai的区别

在人工智能&#xff08;AI&#xff09;领域&#xff0c;大模型一直是一个热议的话题。从之前的谷歌 DeepMind、百度 Big. AI等&#xff0c;再到今天的百度GPT-3,人工智能技术经历了从“有”到“大”的转变。那么&#xff0c;大模型与传统 ai的区别在哪里&#xff1f;这对未来人…

牛客NC97 字符串出现次数的TopK问题【中等 哈希+优先级队列 Java/Go】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/fd711bdfa0e840b381d7e1b82183b3ee 核心 哈希&#xff0c;优先级队列Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返…

deepstream std mean 对应的计算方法

pytorch中经典值mean[0.485, 0.456, 0.406]&#xff0c;std [0.229, 0.224, 0.225] 在deepstream中的计算方法 deepstream 对应计算公式&#xff1a;y net scale factor*(x-mean) &#xff0c;deepstream中mean也叫作offset deepstream中mean(offset)计算方法为&#xff1a…

[力扣]——387.字符串中的第一个唯一字符

. - 力扣&#xff08;LeetCode&#xff09; class Solution {public int firstUniqChar(String s) {int[] count new int[256];// 统计每个字符出现的次数for(int i 0; i < s.length(); i){count[s.charAt(i)];}// 找第一个只出现一次的字符for(int i 0; i < s.lengt…

轻松实现MySQL集群配置:一主一从与一主多从教程

在数据驱动的时代&#xff0c;数据库的高可用性和负载分散成为了维护在线服务稳定运行的关键。MySQL作为世界上最流行的开源关系型数据库管理系统&#xff0c;其集群配置是任何DBA或开发人员必须掌握的技能之一。本文将为您详细介绍如何轻松配置MySQL的一主一从和一主多从集群&…

python基础 面向练习学习python1

python基础 面向练习学习python1 1. 电话查询问题描述1. 问题分析1. 输入输出分析2. 需求分析&#xff1a;将题目的数据存储并查询2. 所需知识&#xff1a; python 数据存储的类型3. 确定数据存储类型4. 如何书写代码拓展 从键盘中添加或删除联系人5. 回到数据查询 代码拓展 功…

QT--day3

1、mywidget.h #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include<QIcon> //图标类 #include<QLabel> //标签类 #include<QMovie> //动图类 #include<QLineEdit> //行编辑器类 #include<QPushButton> //按钮类 #include…

英伟达与AMD锁定台积电先进封装产能,AI市场驱动营收增长

全球AI芯片巨头英伟达和AMD正全力冲刺高效能运算&#xff08;HPC&#xff09;市场&#xff0c;并传出两家公司已预订了台积电2023年和2024年的CoWoS与SoIC先进封装产能。台积电高度看好人工智能相关应用所带来的巨大动能&#xff0c;其总裁魏哲家在4月的法说会上表示&#xff0…