Veamos una lista de opciones que comienzan con las peores y avanzan hacia las mejores. Tendremos una lista aquí y se discuten a continuación:
transform(cbegin(s), cend(s), begin(s), ::tolower)
transform(cbegin(s), cend(s), begin(s), static_cast<int(*)(int)>(tolower))
transform(cbegin(s), cend(s), begin(s), [](const unsigned char i){ return tolower(i); })
El código en su pregunta, transform(s.begin(), s.end(), s.begin(), tolower)
producirá un error como:
No matching function for call to transform(std::basic_string<char>::iterator, std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)
La razón por la que usted estaba recibiendo un "sin resolver sobrecargado tipo de función" es que hay 2 tolower
s en el std
espacio de nombres:
- La biblioteca
locale
define template <typename T> T tolower(T, const locale&)
- La biblioteca
cctype
define int tolower(int)
es el solution offered by davka. Soluciona el error aprovechando el hecho de que locale
's tolower
no está definido en el espacio de nombres global.
Dependiendo de su situación locale
's tolower
puede ameritar consideración. Se puede encontrar una comparación de los tolower
s aquí: Which tolower in C++?
Desafortunadamente depende de cctype
's tolower
siendo definida en el espacio de nombres global. Veamos por qué esto puede no ser el caso:
Usted está utilizando con razón #include <cctype>
, como hacer #include <ctype.h>
ya no se utiliza en C++: http://en.cppreference.com/w/cpp/header
Pero los estados estándar de C++ en D.3 [depr.c.headers ] 2 de las declaraciones en las cabeceras:
It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std
and are then injected into the global namespace scope by explicit using-declarations (7.3.3)
Así que la única manera que podemos garantizar nuestro código es independiente de la implementación es utilizar un tolower
de namespace std
. es el solution offered by David Rodríguez - dribeas.Se aprovecha el hecho de que puede static_cast
:
Be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type
Antes de continuar, permítanme comentar que si encuentra int (*)(int)
a ser un poco confuso se puede leer más en función de la sintaxis de puntero here.
Lamentablemente no es one other issue con el argumento de entrada tolower
's, si:
Is not representable as unsigned char and does not equal EOF, the behavior is undefined
está utilizando un string
que utiliza elementos de tipo: char
. Los estados estándar de char
específicamente 7.1.6.2 [dcl.type.simple] 3:
It is implementation-defined whether objects of char
type are represented as signed or unsigned quantities. The signed
specifier forces char
objects to be signed
lo tanto, si la aplicación define una char
para significar un signed char
entonces tanto y daría lugar a un comportamiento indefinido para todos los caracteres que corresponden a números negativos. (Si una codificación de caracteres ASCII se utiliza los caracteres correspondientes a números negativos se Extended ASCII.)
El comportamiento indefinido se puede evitar mediante la conversión de la entrada a un unsigned char
antes de pasarla a tolower
. logra que utilizando un lambda que acepta un unsigned char
por valor, luego lo pasa a tolower
convirtiendo implícitamente a int
.
Para garantizar comportamiento definido en todas las implementaciones compatibles, independiente de la codificación de caracteres, tendrá que utilizar o algo similar.
El tipo de retorno de 'main' es' int', y los tipos de retorno en C++ tienen que ser explícitos. Algunos compiladores permitirán que el código se publique, pero no es estándar, y podría romperse con la nueva versión del compilador o en otros compiladores. –
@ DavidRodríguez-dribeas C o C++ no requieren un retorno de 'main', devuelve implícitamente 0. Ver los comentarios de esta respuesta: http://stackoverflow.com/a/33442842/2642059 –