问题描述
我试图了解如何使用std::tolower
...
I try to understand how to use std::tolower
...
#include <iostream>
#include <string>
#include <algorithm>
#include <locale>
int main()
{
std::string test = "Hello World";
std::locale loc;
for (auto &c : test)
{
c = std::tolower(c, loc);
}
std::transform(test.begin(), test.end(), test.begin(), ::tolower); // 1) OK
std::transform(test.begin(), test.end(), test.begin(), std::tolower); // 2) Cryptic compile error
std::transform(test.begin(), test.end(), test.begin(), static_cast<int(*)(int)>(std::tolower)); // 3) Cryptic compile error. Seems OK with other compilers though
return 0;
}
所以:
- 为什么
::tolower
版本有效? - 为什么
std::tolower
在std :: transform中不起作用? -
static_cast<int(*)(int)>(std::tolower))
真正在试图做什么?为什么它可用于GCC而不适用于Visual Studio 2013? - 然后如何在std :: transform和Visual Studio 2013中使用
std::lower
?
- Why
::tolower
version is working? - Why
std::tolower
is not working in std::transform? - What
static_cast<int(*)(int)>(std::tolower))
really is trying to do? Whydoes it work with GCC and not with Visual Studio 2013? - How could I use
std::lower
in std::transform with Visual Studio 2013 then?
推荐答案
首先,请注意,这些方法中的没有都以可移植的方式完成了正确的工作!问题是char
可能是带符号的(通常是带符号的),但是tolower()
的版本仅接受正值!那就是您真的想使用std::tolower()
这样的东西:
First off, note, that none of these approaches does the right thing in a portable way! The problem is that char
may be signed (and typically is) but the versions of tolower()
only accept positive values! That is you really want to use std::tolower()
using something like this:
std::transform(test.begin(), test.end(), test.begin(),
[](unsigned char c) { return std::tolower(c); });
(或者,如果您对C ++ 03感到困惑,当然可以使用相应的函数对象).将std::tolower()
(或::tolower()
)用作负值会导致未定义的行为.当然,这仅在签署了char
的平台上才有意义,但是,这似乎是典型的选择.
(or, of course, using a corresponding function object if you are stuck with C++03). Using std::tolower()
(or ::tolower()
for that matter) with a negative value results in undefined behavior. Of course, this only matters on platform where char
is signed which seems, however, to be the typical choice.
要回答您的问题:
- 当包含
<cctype>
时,通常会在名称空间std
和全局名称空间中从标准C库获得各种函数和类型.因此,使用::tolower
通常可以正常使用,但不能保证可以正常使用. - 当包含
<locale>
时,有两个std::tolower
版本可用,一个为int(*)(int)
,一个为char(*)(char, std::locale const&)
.仅使用std::tolower
时,编译器通常无法确定要使用哪个. - 由于
std::tolower
含糊不清,因此使用static_cast<int(*)(int)>(std::tolower)
可以消除使用哪个版本的歧义.我不知道为什么将static_cast<...>()
与VC ++一起使用会失败. - 无论如何,都不应将
std::tolower()
与序列char
一起使用,因为这将导致不确定的行为.在unsigned char
上内部使用std::tolower
使用功能对象.
- When including
<cctype>
you typically get the various functions and types from the standard C library both in namespacestd
as well as in the global namespace. Thus, using::tolower
normally works but isn't guaranteed to work. - When including
<locale>
, there are two versions ofstd::tolower
available, one asint(*)(int)
and one aschar(*)(char, std::locale const&)
. When using juststd::tolower
the compiler has generally no way to decide which one to use. - Since
std::tolower
is ambiguous, usingstatic_cast<int(*)(int)>(std::tolower)
disambiguates which version to use. Why use ofstatic_cast<...>()
with VC++ fails, I don't know. - You shouldn't use
std::tolower()
with a sequences ofchar
s anyway as it will result in undefined behavior. Use a function object usingstd::tolower
internally on anunsigned char
.
值得注意的是,使用函数对象而不是函数指针通常要快很多,因为内联函数对象并不容易,而内联函数指针却不那么容易.在实际上知道函数的地方使用内联函数指针,编译器会变得更好,但是当代的编译器当然并不总是通过函数指针内联函数调用,即使所有上下文都在那里.
It is worth noting that using a function object rather than a function pointer is typically a lot faster because it is trivial to inline the function object but not as trivial to inline the function pointer. Compilers are getting better with inlining the use of function pointers where the function is actually known but contemporary compilers certainly don't always inline function calls through function pointers even if all the context would be there.
这篇关于std :: tolower和Visual Studio 2013的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!