The reason and solution of the error when the transform template function calls the tolower function

1. Error report phenomenon:
1.1. Code executed:

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

Tolower function: convert uppercase letters to lowercase, and keep them if they are not letters.
1.2. The prompt error:

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.

Shows that template parameters could not be inferred.
2, error reason:
in <cctype>which a C version of the statement 函数tolower:

int tolower(int); 

And in the <local>middle also declares one 函数模板tolower:

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

If these two header files are included in the program at the same time (C++ standard header files may include other standard header files. For example <iostream>, include <locale>or <cctype>header files. In this way,Comprises <iostream>may introduce <locale>or <cctype>), since these tolowerfunctions are located in the same stdname space, thus forming a function overloading. In this case, transformwhen the fourth parameter of the == function (also a template function) is tolower,At this time, given toloweronly as a function pointers, lack of function parameter derivation type information required, it is impossible to deduce the type of function, it can not be used to determine which overloads

3. Various methods can be solved:
3.1. Specify the function type:

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. Use wrapper functions: avoid the problems caused by overloading directly using tolower function

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

3.3, calling tolower function under global:
non-template function toloweris actually derived from the standard C library functions, and therefore it is also located in the global namespace std C ++ standard library.Since the tolower function in the std namespace may form a function overload, there is only one tolower function in the global namespace, So you can also directly use tolower in the global namespace:

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

Reference: no matching function for call to'transform

to sum up:

1. The transform template function calls the tolower function and reports an error because it is impossible to decide which tolower overloaded function to use.
2. The simplest way to call global ::tolowerfunctions to avoid conflicts.

Guess you like

Origin blog.csdn.net/qq_33726635/article/details/106862819