C++模板基础(九)

news2025/9/20 6:42:28

完美转发与 lambda 表达式模板

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << '\n';
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << '\n';
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    f(x); //int&
    f(5); //int&&

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename T>
void fun(T input)
//void fun(T& input) //无法将int x = 3;从int转换为int&
//void fun(T&& input) //&&是万能引用,右值引用的变量是左值。输出同void fun(T input)
{
    std::cout << "template<typename T> void fun(T input)\n";
    f(input);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&
    fun(5); //参数是int&&类型,但是调用了void f(int& input)

    return a.exec();
}

在这里插入图片描述

● (C++11) 完美转发: std::forward 函数
– 通常与万能引用结合使用
– 同时处理传入参数是左值或右值的情形

#include<utility>

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename T>
void fun(T&& input)
{
    std::cout << "template<typename T> void fun(T input)\n";
    f(std::forward<T>(input)); //完美转发
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename T>
void fun(T input)
{
    std::cout << "template<typename T> void fun(T input)\n";
    f(std::forward<T>(input)); //完美转发不能处理的情形
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int&& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename... T>
void fun(T... inputs)
{
    std::cout << "template<typename... T> void fun(T... inputs)\n";
    f(std::forward<T>(inputs)...); //包展开技术
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int&& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename... T>
void fun(T&&... inputs) //万能引用参数包
{
    std::cout << "template<typename... T> void fun(T... inputs)\n";
    f(std::forward<T>(inputs)...); //包展开技术
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述
● (C++20) lambda表达式模板

消除歧义与变量模板

struct Str
{
    const static int internal = 3;
};

int p = 5;

template<typename T>
void fun()
{
    //internal是T中的一个具体数据,乘以变量p
    std::cout << T::internal*p << '\n';
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    fun<Str>();
    
    return a.exec();
}

在这里插入图片描述
● 使用 typename 与 template 消除歧义
– 使用 typename 表示一个依赖名称是类型而非静态数据成员

struct Str
{
    using internal = int;
};

template<typename T>
void fun()
{
    //internal是T中的一个数据类型,p是该类型的一个指针
    int x = 5;
    typename T::internal* p = &x; //加上typename表示internal是T中的一个数据类型,消除了歧义
    Str::internal* ptr = &x; //加上限定名Str消除歧义
    std::cout << p << '\n' << ptr << '\n';
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fun<Str>();

    return a.exec();
}

在这里插入图片描述

– 使用 template 表示一个依赖名称是模板
– template 与成员函数模板调用

struct Str
{
    template<typename T>
    static void internal()
    {
        std::cout << "Str::template<typename T> static void internal()\n";
    }
};

template<typename T>
void fun()
{
    //T::internal<int>(); //编译器可能认为<是小于运算符。Warning: Use 'template' keyword to treat 'internal' as a dependent template name
    T::template internal<int>(); //OK,使用了template消除了歧义
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fun<Str>();

    return a.exec();
}

在这里插入图片描述

struct Str
{
    template<typename T>
    void internal() //非static函数
    {
        std::cout << "Str::template<typename T> static void internal()\n";
    }
};

template<typename T>
void fun()
{
    T obj;
    //obj.internal<int>(); //编译器可能认为<是小于运算符。Warning: Use 'template' keyword to treat 'internal' as a dependent template name
    obj.template internal<int>();  //OK,使用了template消除了歧义
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fun<Str>(); //输出同上

    return a.exec();
}

● (C++14) 变量模板
– template T pi = (T)3.1415926;

template<typename T>
T pi = (T)3.141592653;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << pi<double> << '\n';
    std::cout << pi<float> << '\n';
    std::cout << pi<int> << '\n';

    return a.exec();
}

在这里插入图片描述

template<typename T, unsigned v>
unsigned MySize = (sizeof(T) == v);

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << MySize<float, 4> << '\n';
    std::cout << MySize<int, 2> << '\n';

    return a.exec();
}

– 其它形式的变量模板
std::is_same

参考
深蓝学院:C++基础与深度解析
cppreference

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

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

相关文章

MYSQL8窗口函数

MYSQL8窗口函数MYSQL8窗口函数窗口函数分类序号函数--排行榜row_number()示例rank()示例dense_rank()示例partition by对每个分区内的行进行排名不加partition by全局排序开窗聚合函数分布函数CUME_DIST()PERCENT_RANK()前后函数LAG()的用法LEAD()头尾函数其他函数NTH_VALUE()N…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(二):Vue网页端开发

文章目录发送验证码登录退出登录界面控件获取用户信息功能项目地址前端代码的框架采用vue.js elementUI 这套较为简单的方式实现&#xff0c;以及typescript语法更方便阅读。首先添加全局对象&#xff1a; loginForm: 登录表单对象 twoFactorData: 两步验证数据&#xff0c; …

跨平台应用开发进阶(五十九):uni-app实现视屏播放小窗功能

文章目录一、前言二、解决方案三、拓展阅读一、前言 在业务功能开发过程中&#xff0c;需要实现视频直播、播放小窗功能。鉴于目前通过接入火山webSDK实现视频直播、点播功能。需要火山协助配合改造实现小窗功能。 uni-app插件市场也提供了若干插件&#xff0c;经试用效果并不…

从二叉树的角度看快速排序

快速排序本质上可以看作二叉树的前序遍历 快速排序是先将一个元素排好序&#xff0c;然后再将剩下的元素排好序 核心思路依然是分治 快排整体思路 准确的可以说是治分 > 先治 得到分界点后 再分 治&#xff1a;双指针技巧&#xff08;左右指针或者快慢指针&#xff0c;…

【Docker】11、IDEA集成Docker插件实现一键部署SpringBoot项目

日常开发项目的过程中&#xff0c;我们每次需要部署线上的时候&#xff0c;都需要安装一大堆的运行环境&#xff0c;例如&#xff1a;JDK、MySQL、Redis 等&#xff0c;非常花费时间、我们可以使用 Docker 的容器技术&#xff0c;方便快捷地搭建项目启动所需要的运行环境&#…

【微服务笔记15】微服务组件之Config配置中心实现用户认证、配置属性加解密

这篇文章&#xff0c;主要介绍微服务组件之Config配置中心实现用户认证、配置属性加解密。 目录 一、用户认证 1.1、引入security依赖 1.2、服务端ConfigServer添加访问配置 1.3、客户端ConfigClient添加访问配置 二、配置属性加解密 2.1、对称加密 &#xff08;1&#…

逍遥自在学C语言 | 位运算符^的高级用法

前言 在上一篇文章中&#xff0c;我们介绍了|运算符的高级用法&#xff0c;本篇文章&#xff0c;我们将介绍^ 运算符的一些高级用法。 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿 —— …

windows系统管理_文件系统授权规则

NTFS 权限规则 NFTS 权限有一些隐含规则&#xff0c;用户最终有效权限受这些规则的影响&#xff0c;了解并运用这些规则&#xff0c;才能 灵活的分配权限&#xff0c;符合实际需求。 1 权限的累加 如果在某个文件或文件夹的访问控制列表中为某个用户分配了操作权限&#xff…

猿辅导学员入选国家队,竞赛老师成为“最强辅助”

3月31日&#xff0c;国际数学奥林匹克竞赛&#xff08;IMO&#xff09;国家队名单正式出炉&#xff0c;猿辅导学员王淳稷、孙启傲分别以第一名和第二名的成绩位列其中&#xff0c;今年7月&#xff0c;他们将出征日本&#xff0c;代表中国参赛&#xff0c;为国争光。 自2020年以…

理解 与 计算 物联网产品的电池使用寿命

本文带你理解电池的容量以及教会你如何计算使用电池的产品的工作时长前言 在物联网领域&#xff0c;在保证产品性能的前提下&#xff0c;产品的功耗是做得越来越低&#xff0c;针对物联网领域的低功耗无线芯片的功耗也是越来越低。 作为研发人员&#xff0c;除了能够设计出满…

巧用千寻位置GNSS软件|点测量采集技巧

点测量是测量中重要的节点&#xff0c;在测量工作的信息处理分析中发挥着重要作用。本期将给各位带来使用千寻位置GNSS软件采集地形点、控制点、快速点、连续点、房角点和倾斜点的操作技巧。地形点地形点的设置如图 5.1-9所 示&#xff0c;每次采集一个点&#xff0c;该点需要满…

Docker通过Nginx容器代理部署Vue项目

一、打包构建dist 在vue.config.js 添加入口等配置&#xff1a; pages: {index: {// 入口entry: src/main.js}}, lintOnSave: false, publicPath: ./ 在package.json文件中编写build构建&#xff1a; 然后运行: npm run build 在项目根目录下就有构建好的dist包&#xff0…

物流路由线路配载前端算法逻辑实现方案

作者&#xff1a;京东物流 柳宏 1.前置知识 1.1 基本概念 1.1.1 配载 配载代表着某条线路是否具有发往某个方向&#xff08;区域、省市县、分拣等&#xff09;的能力&#xff0c;也可以说是网点&#xff08;分拣中心&#xff09;是否具有承载配载所指方向货物的能力。一般网…

Go 构建基础的事件调度器

&#x1f447;我在这儿 当我们需要在一段时间后的特定时间或间隔运行任务时&#xff0c;我们需要使用任务调度系统来运行任务&#xff1a;例如发送电子邮件、推送通知、午夜关闭账户、清空表格等。在本文中&#xff0c;我们将构建一个基本的事件调度程序&#xff0c;使用数据库…

基于springboot和ajax的简单项目 02.一直会出现的页面的上一页,下一页,分页与总页数 (下)

在各种功能中会一直出现页面分页的问题。 对此&#xff0c;可以使用pojo对象&#xff0c;来一直管理页面分页的功能。 01.创建相关的pojo对象。 由于属性是来辅助sql语句的&#xff0c;这个pojo对象。 Setter Getter ToString NoArgsConstructorpublic class PageObject<T&…

MySQL数据库实现主从同步

安装MySQL数据库8.0.32 前言 今天来学习数据库主从同步的原理及过程&#xff0c;数据库主要是用来存储WEB数据&#xff0c;在企业当中是极为重要的&#xff0c;下面一起来看下。 1.1 数据库做主从的目的 MySQL主从复制在中小企业&#xff0c;大型企业中广泛使用&#xff0c…

【ROS2指南-2】入门 turtlesim 和 rqt

目标&#xff1a;安装并使用 turtlesim 包和 rqt 工具为即将到来的教程做准备。 教程级别&#xff1a;初学者 时间&#xff1a; 15分钟 内容 背景 先决条件 任务 1 安装turtlesim 2 启动turtlesim 3 使用turtlesim 4 安装rqt 5 使用 rqt 6 重新映射 7 关闭turtlesim …

算法 || DFS(深度优先搜索) BFS(广度优先搜索)

&#xff11;、基本概念 dfs全称为Depth First Search,即深度优先搜索。它的思想是沿着每一条可能的路径一个节点一个节点地往下搜索,搜到了路径的到终点再回溯,一直到所有路径搜索完为止。 bfsbfs全称为Breath First Search,即广度(宽度)优先搜索。它的思想是将每一层的结搜…

【SQL】数据库的创建,表的创建、更新、删除

本文内容参考书籍《SQL基础教程》&#xff0c;初学者&#xff0c;请多指教。 一、数据库的创建 1、创建数据库语句 CREATE DATABASE <数据库名称>; 2、示例 CREATE DATABAST shop&#xff1b; 二、表的创建 创建表之前&#xff0c;必须先创建用于存储表的数据库。 1、…

如何找出消耗CPU最多的线程?

如何找出消耗CPU最多的线程&#xff1f; 1.使用 top -c 找出所有当前进程的运行列表 top -c 2.按P(Shiftp)对所有进程按CPU使用率进行排序&#xff0c;找出消耗最高的线程PID ​​​ 显示Java进程 PID 为 136 的java进程消耗最 3.使用 top -Hp PID&#xff0c;查出里面消…