std::tolower and Visual Studio 2013

前端 未结 2 971
深忆病人
深忆病人 2021-01-05 06:19

I try to understand how to use std::tolower...

#include 
#include 
#include 
#include 

        
2条回答
  •  失恋的感觉
    2021-01-05 06:51

    std::tolower is overloaded in C++, it's declared in as

    int tolower(int);
    

    and also in as

    template CharT tolower(CharT, const locale&);
    

    so when you say "std::tolower" you get an ambiguous reference to an overloaded function.

    1. Why ::tolower version is working?

    When you include the one-argument overload is declared in namespace std and might also be declared in the global namespace, depending on the compiler. If you include then it's guaranteed to be included in the global namespace, and ::tolower will work (although note Dietmar's points about when it's not safe). The two-argument overload from is never declared in the global namespace, so ::tolower never refers to the two-argument overload.

    2. Why std::tolower is not working in std::transform?

    See above, it's an overloaded name.

    3. What static_cast(std::tolower)) really is trying to do?

    It tells the compiler you want the int std::tolower(int) overload, not any other overload of std::tolower.

    Why does it work with GCC and not with Visual Studio 2013?

    Probably because you didn't include , or (less likely) it could be a Visual Studio bug.

    4. How could I use std::lower in std::transform with Visual Studio 2013 then?

    If you know you only have characters with values between 0 and 127 then you can include and use ::tolower (because the two-argument version is not declared in the global namespace, only in namespace std) or disambiguate which overload you want with the static cast. An alternative to the cast is to use a local variable:

    typedef int (*tolower_type)(int);
    tolower_type tl = &std::tolower;
    std::transform(b, e, b, tl);
    

    A safer and portable alternative is to use a custom function object (or lambda expression) to call the desired overload safely:

    std::transform(b, e, b, [](unsigned char i) { return std::tolower(i); });
    

    This uses std::tolower with an argument, so the compiler can do overload resolution to tell which overload you want to call. The parameter is unsigned char to ensure we never pass a char with a negative value to tolower(int), because that has undefined behaviour.

    See http://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.simple for more details.

提交回复
热议问题