Re: std::transform with std::use_facet<std::ctype<char> >(std::locale()).toupper()

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Paul wrote:
This works all right:
---------------------
#include <string>
#include <algorithm>
#include <cctype>

std::string s("something");
std::transform(s.begin(), s.end(), s.begin(), std::toupper);
---------------------
(other than a compiler warning about assigning int to char - std::toupper()'s return value is int)

That won't compile if you #include <locale> (since then toupper is overloaded). In addition, it has undefined behaviour if s has any negative characters in it (the domain of toupper is 0-UCHAR_MAX and EOF).


A locale-based replacement for std::toupper - and the one operating on char's rather than int's - is std::use_facet<std::ctype<char> >(std::locale()).toupper() as in this example:
---------------------
for (std::string::iterator p = s.begin(); p != s.end(); ++p)
*p = .toupper(*p);

I'd pull the facet creation out of the loop. e.g.
std::ctype<char> const& ct =
std::use_facet<std::ctype<char> >(std::locale());
for (std::string::iterator p = s.begin(); p != s.end(); ++p)
*p = ct.toupper(*p);


---------------------
which I tried to incorporate into std::transform() as in the first example but could not make it. Can this be done?

//need target type since toupper is overloaded.
char (std::ctype<char>::*fptr)(char) const = &std::ctype<char>::toupper;
std::transform(
s.begin(),
s.end(),
s.begin(),
std::bind1st(
std::mem_fun(fptr),
&std::use_facet<std::ctype<char> >(std::locale())
)
);

However, it may well run slower than the loop, if it fails to inline the member function calls. It's also less clear than the loop. Finally, there is also a non-member function in <locale>
char toupper(char, std::locale const&); //actually, it's templated IIRC

However, I'd generally avoid these machinations and instead use the boost string library: http://www.boost.org/doc/html/string_algo.html

Also, both

int main(int argc, char* argv[]);

and

VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv);

take non-constant arguments (char* and LPTSTR*, respectively). Is this all right to use the above routine to convert them to upper case?

I think so.

Obviously, I
am not altering them in any other way and do not "extend" them - just perform upper-case conversion. I know it works and have so far had no problems but just in case.

It is explicitly defined as legal to modify the argv strings in the C standard, though the C++ standard doesn't say anything about whether you can modify them.

Tom
.



Relevant Pages

  • Re: Reading from files and range of char and friends
    ... Using symmetry and 1) we get that SRAR(unsigned char*, ... The footnote about interchangeability does not impose any actual ... Couldn't we instead resolve the contradiction by saying that the belief ... The standard doesn't define "same" and it wouldn't be the first time ...
    (comp.lang.c)
  • Re: Destructor: not gauranteed to be called?
    ... >>> the ToStringmethod to a Char[] it returns with the EXACT SAME ... >>> the standard and might break someone's existing code. ... ToString is not part of the C++ ... The fact yhat you require or expect a Charto act as a string is a sign ...
    (microsoft.public.dotnet.languages.vc)
  • Re: Why is the pointer passed into the function still NULL?
    ... The routine can modify those named parameters, ... void get_table (char ** table) { ...
    (comp.lang.c)
  • Re: byte order
    ... int am_i_little_endian{ ... Are you *absolutely* sure that's standard C, ... assuming a 8-bit char). ... The pointer casting rules specify that "It is guaranteed that ...
    (comp.lang.lisp)
  • Re: An Observation
    ... You execute it now or you execute it later. ... I explained CHAR and as I did in my prior post in ... complexity around and was not actually any simpler. ... because of the sloppiness of the standard. ...
    (comp.lang.forth)