transform模板函数调用tolower函数报错原因、解决办法

1、报错现象:
1.1、执行的代码:

string s = "Abcd. ,,cD";
transform(s.begin(), s.end(), s.begin(), tolower);

tolower作用:是大写字母则转换为小写,不是字母则保持不动。
1.2、提示的错误:

Line 5: Char 9: fatal error: no matching function for call to 'transform'
        transform(s.begin(), s.end(), s.begin(), tolower);
        ^~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_algo.h:4293:5: 
note: candidate template ignored: couldn't infer template argument '_UnaryOperation'
1 error generated.

显示无法推断模板参数。
2、报错原因:
<cctype>里面声明了一个C版本的函数tolower

int tolower(int); 

而在<local>中间也声明了一个函数模板tolower

template <class charT>
charT tolower( charT c , const locale& loc );

如果这两个头文件都同时包含到程序中来的话(C++标准头文件可能会包含另外的标准头文件。例如<iostream>,会包含<locale><cctype>头文件。这样,包含<iostream>可能会引入<locale><cctype>),由于这些 tolower 函数都位于同一 std 名字空间,于是形成了函数重载。这样的话,==transform 函数(也是一个模板函数)的第四个参数是tolower 的时候,此时给定的 tolower 只是作为一个函数指针使用,缺乏类型推导所需要的函数参数信息,所以无法推导出函数的类型,也就无法决定使用哪一个重载函数

3、多种方法可以解决:
3.1、指明函数类型:

transform( s.begin(), s.end(), s.begin(), (int(*)(int))tolower);
或者
int (*pf)( int ) = tolower; // pf 是一个函数指针,其类型已经明确。
transform( s.begin(), s.end(), s.begin(), pf );

3.2、使用包装函数:避免直接使用 tolower 函数由于重载带来的问题

int my_tolower( int c )
{
    
    
return tolower( c ); // 根据 c 的类型可以确定使用 tolower 的哪个重载函数。
}
// my_tolower 是非模版非重载函数,避免了函数重载带来的类型解析问题。
transform( s.begin(), s.end(), s.begin(), my_tolower );

3.3、调用全局下的tolower函数:
非模板函数的 tolower 其实是来自于标准 C 库函数,因此在 C++ 标准库中它同时位于全局和 std 名字空间。既然 std 名字空间内 tolower 函数有可能形成函数重载,但是在全局名字空间中的 tolower 函数却只有一个,所以也可以直接使用全局名字空间中的 tolower:

transform( s.begin(), s.end(), s.begin(), ::tolower);

参考资料:no matching function for call to ‘transform

总结:

1、transform模板函数调用tolower函数报错是因为无法决定使用哪一个tolower的重载函数。
2、最简单的调用全局下的::tolower函数避免冲突。

猜你喜欢

转载自blog.csdn.net/qq_33726635/article/details/106862819
今日推荐