C++模板基础(九)

完美转发与 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp - 全平台兼容的 “多图上传“ 功能,搭配 uview 组件库中的 upload 上传组件(附带详细的示例源码及注释,可直接复制使用或简单修改)

效果图 使用 uniapp 开发,多平台全端兼容的多图上传功能,支持限制个数及移除等。 组件库使用的是 uview 框架,上传组件基于 Upload组件,功能完美无bug。 准备阶段 Upload组件支持手动上传与

Docker安装Elasticsearch详细步骤

1 安装elasticsearch 1.1 拉取镜像 docker pull elasticsearch:7.12.11.2 创建挂载目录 mkdir -p /app/elasticsearch/confecho "http.host: 0.0.0.0" >> /app/elasticsearch/conf/elasticsearch.ymlmkdir -p /app/elasticsearch/datamkdir -p /app/elastic…

GaussDB工作级开发者认证—第三章开发设计建议

一. 数据库对象命名和设计建议 二. 表设计最佳实践 三. SQL查询最佳实践 SQL 最佳实践 - SELECT 避免对大字段执行order by&#xff0c;group by等引起排序的操作避免频繁使用count()获取大表行数慎用通配符字段 “*”避免在select目标列中使用子查询统计表中所有记录数时&…

Leetcode刷题之环形链表

莫等闲&#xff0c;白了少年头&#xff0c;空悲切。 --岳飞 目录 1.环形链表 2.环形链表Ⅱ 1.环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next …

想制作出专业水准的音视频?掌握H.264编码技巧是关键

H.264编码原理 H.264&#xff0c;也被称为先进视频编码&#xff08;AVC&#xff09;&#xff0c;是目前最流行的视频编码标准之一&#xff0c;其压缩效率很高。H.264编码基于视频编码的原始数据&#xff0c;使用一系列算法和技术以更小的比特率呈现更高质量的视频。以下是H.26…

SpringBoot整合xxl-job详细教程

SrpingBoot整合xxl-job&#xff0c;实现任务调度说明调度中心执行器调试整合SpringBoot说明 Xxl-Job是一个轻量级分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。Xxl-Job有…

主机发现和端口扫描基本原理和工具选择

发现主机 扫描端口指令sudo nmap -sn ip 实则是封装ping指令 可以找目标靶机 sudo nmap --min-rate 10000 -p- 192.168.10.191 -p端口号 -p-从一开始扫 设置最小速度扫描 -p-指定靶机 10000是较好的速度 在工作中最好扫两遍 UDP扫描 sudo nmap -sU --min-rate 10000 …

Golang每日一练(leetDay0035) 二叉树专题(4)

目录 103. 二叉树的锯齿形层序遍历 Binary Tree Zigzag Level Order Traversal &#x1f31f;&#x1f31f; 104. 二叉树的最大深度 Maximum Depth of Binary-tree] &#x1f31f; 105. 从前序与中序遍历序列构造二叉树 Construct-binary-tree-from-preorder-and-inorder-…

一文弄懂访问者模式

关于设计模式&#xff0c;我们得结合生活中的案例来学习&#xff1b;最近我在网上也看了不少文章&#xff0c;今天想跟大家分享一下关于访问者模式的一些知识&#xff0c;先来看一个简单的案例吧。 相信大家都去过医院&#xff0c;看完病&#xff0c;医生都会给我们开一个处方…

2023最新面试题-Java-6

1. Date API Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多&#xff0c;但 又不完全一样&#xff0c;下面的例子展示了这组新API里最重要的一些部分&#xff1a; Clock类提供了访问当前日期和时间的方法&#xff0c;Clock是时区敏…

环境变量概念详解!(4千字长文)

环境变量&#xff01; 文章目录环境变量&#xff01;环境变量PATHexportexport的错误用法定义命令行变量环境变量哪里来的其他各种环境变量HOMEHOSTNAMELOGNAMEHISTSIZEPWD环境变量相关指令echoenvgetenv——相关函数&#xff01;exportsetunset命令行参数argcargvenvpenvironp…

自动化面试题4

1、工业中常见的通信方式都有哪些&#xff0c;各自特点是什么&#xff1f; 2、对于一台新的伺服驱动器来说&#xff0c;需要设置哪几个方面的参数&#xff1f; &#xff08;1&#xff09;参数初始化 &#xff08;2&#xff09;点动测试电机旋转方向 &#xff08;3&#xff09;惯…

Android创建项目

目录 创建Android项目 配置项目结构 创建安卓模拟器 模拟器运行 HelloWorld 应用 真机运行 HelloWorld 应用 创建Android项目 打开 Android studio 工具&#xff0c;选择Project&#xff0c;选择 New Project 由于现在是教程博客&#xff0c;所以我们随便选择 一个 空 Ac…

Java使用elasticjob实现定时任务(v2.1.5)

elastic是一个定时任务库 https://shardingsphere.apache.org/elasticjob/index_zh.html 项目结构 ​依赖 <dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-core</artifactId><version>2.1.5</version>&…

5.Java循环控制语句

Java循环控制语句 循环是Java中应用最为广泛的一个知识点&#xff0c;所以也是很需要掌握的。所谓循环&#xff0c;即通过判断条件&#xff0c;重复执行一段代码&#xff0c;根据条件的变化&#xff0c;来确定代码是否执行&#xff0c;执行次数。 一、循环结构 1、while循环…

C风格的字符串赋值方式

文章目录&#xff08;1&#xff09;C语言中&#xff0c;没有字符串类型但可以用字符数组模拟字符串。&#xff08;2&#xff09;C语言中&#xff0c;字符串是以’\0’作结尾字符。&#xff08;3&#xff09;C语言中&#xff0c;字符串常量本质上是一个无名的字符数组。C风格的字…

代码自动发布系统

之前是jenkins发现gitlab代码更新了就自动获取直接部署到服务器 现在是jenkins自动获取Code之后打包成镜像上传到仓库然后通知docker去拉取更新的镜像 分析 旧∶ 代码发布环境提前准备&#xff0c;以主机为颗粒度静态 新: 代码发布环境多套&#xff0c;以容器为颗粒度编译 …

适合销售使用的CRM系统特点

销售人员抱怨CRM系统太复杂&#xff0c;这是一个很重要的问题。毕竟&#xff0c;如果系统太难使用&#xff0c;会导致CRM实用率和效率下降&#xff0c;最终影响公司的运作。在这篇文章中&#xff0c;我们来探讨当销售抱怨crm客户系统太复杂了&#xff0c;企业该如何解决。 缺少…

VCS4 debug with DVE

1、重点讲解&#xff1a; 在verilog源代码中嵌入VCD 系统函数&#xff0c;重点如testbench文件中。VCD文件是VCS产生的仿真波形文件&#xff0c;未经压缩&#xff0c;占用空间较大。VCD是压缩后的波形文件。 编译、仿真以生成VCD文件。 在后处理模式中使用激活DVElog对产生的…

NodeJS Cluster模块基础教程

Cluster简介 默认情况下&#xff0c;Node.js不会利用所有的CPU&#xff0c;即使机器有多个CPU。一旦这个进程崩掉&#xff0c;那么整个 web 服务就崩掉了。 应用部署到多核服务器时&#xff0c;为了充分利用多核 CPU 资源一般启动多个 NodeJS 进程提供服务&#xff0c;这时就…