赞
踩
用到这样一个函数,将小写字符串转为大写。
// 一开始个人是这样写的,这样没问题
std::transform(res.begin(), res.end(), res.begin(),[](unsigned char c) { return std::toupper(c); });
// 然后,看到这样的写法
std::transform(res.begin(), res.end(), res.begin(),::toupper);
// 哎,::toupper前面怎么没加std,但加上后就会报错,正文为此问题的探究
// No matching function for call to 'transform' candidate template ignored: couldn't infer template argument '_UnaryOperation' candidate function template not viable: requires 5 arguments, but 4 were provided
在C++中,std::toupper 函数有两种版本,分别定义在头文件 <cctype> 中:
全局函数版本:
int toupper(int c);
// 同所有其他来自 <cctype> 的函数,若参数值既不能表示为 unsigned char 又不等于 EOF 则 std::toupper 的行为未定义。为了以简单的 char (或 signed char )安全使用此函数,首先要将参数转换为 unsigned char,这是因为当字符的值是负数时,传参给int会发生符号扩展,使用 unsigned char 类型可以确保在字符转换时不会发生符号扩展,从而得到正确的结果。
char my_toupper(char ch){
return static_cast<char>(std::toupper(static_cast<unsigned char>(ch)));
}
// 类似
std::string str_toupper(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
// static_cast<int(*)(int)>(std::toupper) // 错误
// [](int c){ return std::toupper(c); } // 错误
// [](char c){ return std::toupper(c); } // 错误
[](unsigned char c){ return std::toupper(c); } // 正确
);
return s;
}
这是最常用的版本,来自标准 C 库函数,且同时位于全局和 std 名字空间,接受一个整数参数 c,返回将小写字母转换为大写字母后的整数值。如果 c 不是小写字母,它将保持不变。
函数模板版本:
template< class CharT >
CharT toupper( CharT ch, const std::locale& loc );
这个版本是函数模板,接受一个字符 ch 和一个 std::locale 对象。它返回将字符 ch 在指定语言环境下转换为大写形式的结果。这个版本通常用于多语言环境下的字符转换。
在这两个版本中,全局函数版本通常用得更广泛,而函数模板版本用于特定的多语言环境需求。在实际编程中,通常使用全局函数版本来进行字符大小写转换。
故当transform 函数(也是一个模板函数)的第四个参数是std::toupper的时候,此时给定的 tolower 只是作为一个函数指针使用,缺乏类型推导所需要的函数参数信息,所以无法推导出函数的类型,也就无法决定使用哪一个重载函数。故解决方法如下:
指明函数类型
std::transform(res.begin(), res.end(), res.begin(),(int(*)(int))std::toupper);
使用包装函数确定函数类型
int my_toupper( int c ) {
return toupper( c ); // 根据 c 的类型可以确定使用 toupper 的哪个重载函数。
}
// my_toupper 是非模版非重载函数,避免了函数重载带来的类型解析问题。
transform( s.begin(), s.end(), s.begin(), my_toupper );
调用全局下的tolower函数,版本1和2都位于std命名空间下,但版本1还位于全局空间下,故可以直接指定命名空间为全局的那个tolower函数
std::transform(res.begin(), res.end(), res.begin(),::toupper);
故tolower函数也是一样的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。