C++基础——使用字符串作为函数模板的实参
在<C++基础——一些细节、常犯错误的汇总>一文的细节3中,我们看到,
const char* s = "hello";
s
的类型是const char*
,"hello"
的类型是const char[6]
是数组类型,也就是与"hell"
(const char[5])具有不同的数据类型。
这一点在函数模板(以字符串为参数)的设计中,显得尤为重要。
template<typename T>
inline const T& max(const T& x, const T& y)
{return x > y ? x : y;
}int main(int, char**)
{::max("hello", "world"); // 正确,具有相同的实参类型,const char[6],// 这样在类型推导时都能匹配到同一个类型::max("hello", "hell"); // 错误, 不同类型的实参std::string s("world");::max("hello", s); // 错误, const char[6] 与 string是不同的类型return 0;
}
如果声明的是非引用参数,就可以使用长度不同的字符串作为max()的参数:
template<typename T>
inline T max(T x, T y)
{return x > y ? x : y;
}
int main(int, char**)
{::max("hello", "world"); // 正确,具有相同的实参类型,const char[6],// 这样在类型推导时都能匹配到同一个类型::max("hello", "hell"); // 正确, decay(退化)为相同的类型std::string s("world");::max("hello", s); // 错误,不同的类型return 0;
}
产生在这种调用的原因是:对于非引用类型的参数,在实参演绎的过程中会出现数组到指针(pointer-to-array)的类型转换(这种转型通常也被称为decay),果真如此奇妙吗,我们不妨使用typeid
关键字加以验证:
template<typename T>
void ref(const T& x)
{cout << "x in ref(const T&): " << typeid(x).name() << endl;
}template<typename T>
void noref(T x)
{cout << "x in noref(T): " << typeid(x).name() << endl;
}int main(int, char**)
{::ref("hello"); // const char [6]::noref("hello"); // const char* return 0;
}
在上述的main函数中,分别将一个字符串(”hello”,类型为const char [6])传递给具有引用参数的函数模板和具有非引用参数的函数模板。通过打印的结果我们可以看到,参数为引用的函数模板和参数不是引用的函数模板在对待字符数组和字符串指针之间存在着一些隐蔽的不同。对这一问题并没有太好的方法,根据不同的情况,可以:
使用非引用参数,取代引用参数,
杀敌一千,自损八百,导致无用的拷贝
重载版本1,分别编写参数为引用类型地函数模板,和参数为非引用类型的函数模板
这可能会导致二义性的出现;
重载版本2,重载数组类型
template<typename T, int N, int M> // 存在两个非类型模板参数
inline const T* max(const T (*x)[N], const T (*y)[M])
{return x > y ? x : y;
}
事实上我们更倾向于使用,std::string
c++风格的字符串类,而不是c风格字符串类,这又牵涉到C++和C语言风格的问题了。C++是一种语言联邦,支持多编程范式。我们在之前的文章中有谈到,两种语言风格下的类型转换问题,<C++基础——C++风格的类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast>。
C++基础——使用字符串作为函数模板的实参相关推荐
- Python 基础之字符串操作,函数及格式化format
一.字符串的相关操作 1.字符串的拼接 + strvar1 = "我爱你," strvar2 = "亲爱的姑凉" res = strvar1 + strvar2 ...
- C++模板剖析:函数模板、类模板解析
C++中关于模板&泛型编程问题: 问题引入:何编写一个通用加法函数? (1)使用函数重载,针对每个所需相同行为的不同类型重新实现它 int Add(const int &_iLef ...
- C++知识点55——函数模板
一.为啥需要模板 防止相同功能的重复实现 二.函数模板 1.模板函数的定义 template <typename T> const T& Max(const T &a, c ...
- 什么是函数模板以及什么是类模板
[1]模板的含义 (1) 模板就是实现代码重用的机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性. (2) 模板可以分为两类,一个是函数模板,另外一个是类模板. ...
- C++中函数模板的返回值是模板类型参数的调用方法
1 函数模板 模板定义以关键字template开始,后接模板形参表,模板形参表是用尖括号扩住的一个或多个模板形参的列表,形参之间以逗号分隔.关于函数模板的详细介绍,请参考<C++中模板函数及模板 ...
- 黑马程序员C语言基础(第五天)运算符与表达式、程序流程结构、数组和字符串、函数
https://www.bilibili.com/video/BV15W411K7k6?p=93&spm_id_from=pageDriver 黑马程序员C语言基础(第五天)运算符与表达式.程 ...
- php课程 6-20 字符串基础和去除空格和字符串填补函数
php课程 6-20 字符串基础和去除空格和字符串填补函数 一.总结 一句话总结: 二.字符串 字符串定义: $str='hello world!'; 输出字符串: echo $str; print ...
- ES6(二)——字符串模板、标签模板字符串、函数的默认参数、剩余参数、数组对象的展开语法、数值的表示、Symbol
一.字符串模板基本使用 在ES6之前,如果我们想要将字符串和一些动态的变量(标识符)拼接到一起,是非常麻烦和丑陋的(ugly). ES6允许我们使用字符串模板来嵌入JS的变量或者表达式来进行拼接: 首 ...
- C++基础:模板,函数模板和类模板
文章目录 1. 函数模板 2. 类模板 3. 模板特化 3.1 函数模板特化 3.2 类模板特化 4. 非类型模板参数 模板是允许函数或类通过泛性的形式表现或运行的特性 1. 函数模板 模板可以使函数 ...
最新文章
- β射线与哪些物质可产生较高的韧致辐射_辐射防护试题库(无评分标准)
- stm32 独立看门狗学习
- 同事更新几个表_最近计划学习的几个网站资源
- k2698场效应管参数电流_mos管特性曲线-电流方程与参数详解
- 百度AI实力响应“新基建”号召 Q1财报智能交通成绩亮眼
- Apache Pulsar的多租户消息系统
- 爆笑~~偶和老公滴愚人笑话~~~
- 工程力学考研 可以转计算机专业吗,跨专业考研我是工程力学的本科生,想要考飞行 – 手机爱问...
- tomcat 日志切割
- 动软出现“添加服务器配置失败,请检查是否有写入权限或文件是否存在“错误
- 随机矩阵理论_随机PWM可降低噪声并减少三相逆变器应用中的辐射
- 在字节跳动实习的真实感受究竟如何?
- win8专业版和win8.1专业版安装密钥key及其永久激活工具
- Qt----Qt控制LED
- Java实现蓝桥杯VIP算法训练 预测身高
- 服务器重启后samba启动不了,提示stop: Unknown instance: smbd start/running, process 76585
- 怎么选择自己合适的LED驱动IC?
- Java实现 蓝桥杯算法提高金明的预算方案
- 微信公众号如何和Salesforce集成,然后后台给公众号的关注者推送模板消息?
- 生成签名证书keystore