模板类型的推断

下面的函数f是个模板函数,typename T。下表是,根据调用测的实参,推断出来的T的类型。

请注意下表的红字部分, f(T&& t)看起来是右值引用,但其实它会根据实参的类型,来决定T的类型,如果实参是左值,则它是左值,如果实参是右值,则它是右值。

所以可以看出来,T&可以变成const& ,f(T&& t)也可以变成const&。

f(T t) f(const T t) f(T& t) f(const T& t) f(T&& t) f(const T&& t)
f(1) f<int> f<int> error cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int' f<int> f<int> f<int>
int i = 1;
f(i);
f<int> f<int> f<int> f<int> f<int&> error cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘int’
int& ri = i;
f(ri);
f<int> f<int> f<int> f<int> f<int&> cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘int’
const int ci = 2;
f(ci);
f<int> f<int> f<const int> f<int> f<const int&> cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘const int’
const int& rci = ci;
f(rci);
f<int> f<int> f<const int> f<int> f<const int&> cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘const int’

实验代码

#include <iostream>

template<typename T>
void f1(T t){
t = 99;
} template<typename T>
void f4(const T t){
//t = 99;
} template<typename T>
void f2(T& t){
//t = 99;
} template<typename T>
void f3(const T& t){} template<typename T>
void f5(T&& t){} template<typename T>
void f6(const T&& t){} int main(){
/*
//void f1(T t)
f1(1);//int
int i = 1;
f1(i);//int
int& ri = i;
f1(ri);//int
std::cout << ri << std::endl;
const int ci = 2;
f1(ci);//int
const int& rci = ci;
f1(rci);//int
*/ /*
//void f4(const T t)
f4(1);//int
int i = 1;
f4(i);//int
int& ri = i;
f4(ri);//int
std::cout << ri << std::endl;
const int ci = 2;
f4(ci);//int
const int& rci = ci;
f4(rci);//int
*/ /*
//void f2(T& t)
//f2(1);//error cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
int i = 1;
f2(i);//int
int& ri = i;
f2(ri);//int
const int ci = 2;
f2(ci);//const int
const int& rci = ci;
f2(rci);//const int
*/ /*
//void f3(const T& t)
f3(1);//int
int i = 1;
f3(i);//int
int& ri = i;
f3(ri);//int
const int ci = 2;
f3(ci);//int
const int& rci = ci;
f3(rci);//int
*/ /*
//void f5(T&& t)
f5(1);//int
int i = 1;
f5(i);//int&
int& ri = i;
f5(ri);//int&
std::cout << ri << std::endl;
const int ci = 2;
f5(ci);//const int&
const int& rci = ci;
f5(rci);//const int&
*/ /*
//void f6(const T&& t)
f6(1);//int
int i = 1;
//f6(i);//error cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘int’
int& ri = i;
//f6(ri);//error cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘int’
std::cout << ri << std::endl;
const int ci = 2;
//f6(ci);//error cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘const int’
const int& rci = ci;
//f6(rci);//error cannot bind rvalue reference of type ‘const int&&’ to lvalue of type ‘const int’
*/ }

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

c/c++ 模板 类型推断的更多相关文章

  1. [Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断

    条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 t ...

  2. 现代C++之理解模板类型推断(template type deduction)

    理解模板类型推断(template type deduction) 我们往往不能理解一个复杂的系统是如何运作的,但是却知道这个系统能够做什么.C++的模板类型推断便是如此,把参数传递到模板函数往往能让 ...

  3. 现代C++之理解auto类型推断

    理解auto类型推断 上一篇帖子中讲述了模板类型推断,我们知道auto的实现原理是基于模板类型推断的,回顾一下模板类型推断: template <typename T> void f(Pa ...

  4. jdk8系列二、jdk8方法引用、重复注解、更好的类型推断、新增注解

    一.方法引用 方法引用使得开发者可以直接引用现存的方法.Java类的构造方法或者实例对象.方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码. 方法 ...

  5. 【C++ Primer 第16章】2. 模板实参推断

    模板实参推断:对于函数模板,编译器利用调用中的函数实参来确定模板参数,从函数实参来确定模板参数的过程被称为模板实参推断. 类型转换与模板类型参数 与往常一样,顶层const无论在形参中还是在是实参中, ...

  6. C++学习笔记(4)----模板实参推断

    1. 如图所示代码,模板函数 compare(const T&, const T&) 要求两个参数类型要一样. compare("bye","dad&qu ...

  7. C++ 自动类型推断

    C++语言提供了自动类型推断的机制,用于简化代码书写,这是一种很不错的特性,使用auto和decltype都可以完成自动类型推断的工作,而且都工作在编译期,这表示在运行时不会有任何的性能损耗. 一.a ...

  8. C++ Templates (1.2 模板实参推断 Template Argument Deduction)

    返回完整目录 目录 1.2 模板实参推断 Template Argument Deduction 1.2 模板实参推断 Template Argument Deduction 当调用函数模板(如max ...

  9. C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)

    #include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...

随机推荐

  1. css对齐方案总结

    css对齐方案总结 垂直居中 通用布局方式(内敛元素和块状元素都适用) 利用flex:核心代码: 12345 .container{ display:flex; flex-direction:colu ...

  2. 安卓开发笔记(二十五):ViewPager的使用

    首先我们来看看运行之后的效果: 然后我们也不多说废话了,下面是这个项目所需要的全部代码,很多博主写这个都不把代码写完,因此笔者自己也琢磨了一会儿才把这个弄出来,感觉很烦,但我肯定会把代码写全的.我这里 ...

  3. Windows Server 安装后无法使用无线与音频

    1.无线 运行powershell,输入命令: install-windowsfeature Wireless-Networking 之后重启. 运行cmd输入: sc config WlanSvc ...

  4. #if和#ifdef的区别

    学习STM32偶然发现:在Keil中直接预先定义宏USE_STDPERIPH_DRIVER,但是却没有指定宏的值.而在头文件中判断用的是如下代码: #ifdef USE_STDPERIPH_DRIVE ...

  5. windows server 2008 R2 Enterprise 系统安全配置

    window 安全配置规则 一.开启防火墙 二.允许远程网络进行远程桌面连接 如果使用默认的远程端口的话,按照下图,允许远程桌面通过防火墙就行了: 如果你的远程端口号不是默认的,则需要按照(四)中新建 ...

  6. C#异步编程----Thread

    一.问题由来 多线程能实现的基础: 1.CPU运行速度太快,硬件处理速度跟不上,所以操作系统进行分时间片管理.这样,宏观角度来说是多线程并发 ,看起来是同一时刻执行了不同的操作.但是从微观角度来讲,同 ...

  7. Eureka源码探索(一)-客户端服务端的启动和负载均衡

    1. Eureka源码探索(一)-客户端服务端的启动和负载均衡 1.1. 服务端 1.1.1. 找起始点 目前唯一知道的,就是启动Eureka服务需要添加注解@EnableEurekaServer,但 ...

  8. 5.Flask-Migrate

    1.1.项目结构重构 (1)config.py DB_URI = "mysql+pymysql://root:123456@127.0.0.1:3306/flask_migrate?char ...

  9. 最简单的SpringBoot整合MyBatis教程

    前面两篇文章和读者聊了Spring Boot中最简单的数据持久化方案JdbcTemplate,JdbcTemplate虽然简单,但是用的并不多,因为它没有MyBatis方便,在Spring+Sprin ...

  10. AssetsUtils【读取assets、res/raw、./data/data/包名/目录下的文件】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 封装了以下功能: 1.读取assets目录下的资源html.文件.图片,将文件复制到SD卡目录中: 2.读取res/raw目录下的文 ...