Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::tolower and Visual Studio 2013

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;
}

So:

  1. Why ::tolower version is working?
  2. Why std::tolower is not working in std::transform?
  3. What static_cast<int(*)(int)>(std::tolower)) really is trying to do? Why does it work with GCC and not with Visual Studio 2013?
  4. How could I use std::lower in std::transform with Visual Studio 2013 then?
like image 959
Korchkidu Avatar asked Nov 09 '13 13:11

Korchkidu


People also ask

Is Visual Studio 2012 update 3 compatible with Visual Studio 2013?

In addition, Visual Studio 2012 Update 3 contains improvements for project compatibility between Visual Studio 2012 and Visual Studio 2013, and resolves compatibility issues for Visual Studio 2012 on Windows 8.1. .NET 4.5.1 is a highly compatible in-place update of .NET 4 and .NET 4.5.

Can I use Visual Studio 2012 on Windows 8?

When installed on Windows 8.1, Visual Studio 2012 continues to support creation of Windows Store apps for Windows 8 and Windows Phone 8. In addition, Visual Studio 2012 Update 3 contains improvements for project compatibility between Visual Studio 2012 and Visual Studio 2013, and resolves compatibility issues for Visual Studio 2012 on Windows 8.1.

Can Windows Store apps be opened in Visual Studio 2012?

Windows Store app projects for Windows 8.1 and Windows Phone 8.1 cannot be opened in earlier versions of Visual Studio. You can install and use Visual Studio 2013 alongside Visual Studio 2012. When installed on Windows 8.1, Visual Studio 2012 continues to support creation of Windows Store apps for Windows 8 and Windows Phone 8.

Does Visual Studio 2013 support migration from Windows Phone 7 to 8?

Visual Studio 2013 supports migration of Windows Phone 7 and 7.5 projects to Windows Phone 8. Requires Visual Studio 2013 Update 2 or later. Windows Phone emulator installed on demand. Supports migration of Windows Phone 8 projects to Windows Phone Silverlight 8.1.


1 Answers

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); });

(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.

To answer your questions:

  1. When including <cctype> you typically get the various functions and types from the standard C library both in namespace std as well as in the global namespace. Thus, using ::tolower normally works but isn't guaranteed to work.
  2. When including <locale>, there are two versions of std::tolower available, one as int(*)(int) and one as char(*)(char, std::locale const&). When using just std::tolower the compiler has generally no way to decide which one to use.
  3. Since std::tolower is ambiguous, using static_cast<int(*)(int)>(std::tolower) disambiguates which version to use. Why use of static_cast<...>() with VC++ fails, I don't know.
  4. You shouldn't use std::tolower() with a sequences of chars anyway as it will result in undefined behavior. Use a function object using std::tolower internally on an unsigned 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.

like image 197
Dietmar Kühl Avatar answered Oct 05 '22 08:10

Dietmar Kühl