开发者

Whats going on here with cctype?

开发者 https://www.devze.com 2023-02-19 20:42 出处:网络
To my surprise the following code compiles: #include <iostream> #include <string> #include <algorithm>

To my surprise the following code compiles:

#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>

int main() {
   std::string s="nawaz";
   std::string S;
   std::transform(s.begin(),s.end(), std::b开发者_高级运维ack_inserter(S), ::toupper);
   std::cout << S ;
}

I had expected it to fail because of the ::toupper which I believed should be in the std namespace. A quick check of cctype shows that it is but it is imported from the root namesapce (Mystery solved there).

namespace std
{
  // Other similar `using` deleted for brevity.
  using ::toupper;
}

So first problem solved but if I change the transform() line above too:

std::transform(s.begin(),s.end(), std::back_inserter(S), std::toupper);

I would now expect this to now also compile. But I get a compiler error:

kk.cpp:12: error: no matching function for call to `transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::cha r_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'

Which with manual editing resolved too:

kk.cpp:12: error: no matching function for call to
         `transform(iterator<std::string>,
                    iterator<std::string>,
                    std::back_insert_iterator<std::string>,
                    <unresolved overloaded function type>)'

What am I missing?


It doesn't work because there are overloads of std::toupper. You can fix it by casting to your desired function overload:

std::transform(s.begin(),s.end(), std::back_inserter(S),
                (int(&)(int))std::toupper);


You're missing that C++ also adds new toupper functions in <locale> which is probably included implicitly by one of your other headers. Thus in the std:: namespace there are multiple overloads while in the global namespace there is only the old C version of the function.

That said it does still seem like g++ should be able to deduce the correct overload.


Like others said the problem is that std::toupper and friends are overloaded. One way to fix this is to use a lambda.

#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>

int main()
{
   std::string s{ "This is a test" };
   std::string S{};
   std::transform(s.begin(), s.end(), std::back_inserter(S), [] (char ch){ return std::toupper(ch); });
   std::cout << S;
   return 0;
}

I realize this is an old post but as many, including myself, still encounter this issue, I hope my post will be helpful.

0

精彩评论

暂无评论...
验证码 换一张
取 消