Что происходит здесь с cctype?

К моему удивлению, следующий код компилируется:

#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::back_inserter(S), ::toupper);
   std::cout << S ;
}

Я ожидал, что он потерпит неудачу из-за ::toupper, который, как я полагал, должен находиться в пространстве имен std. Быстрая проверка cctype показывает, что она есть, но она импортируется из корневого имени (таинство разрешено там).

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

Итак, первая проблема решена, но если я тоже изменил строку transform():

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

Теперь я ожидаю, что это тоже скомпилируется. Но я получаю ошибку компилятора:

kk.cpp: 12: ошибка: нет соответствующей функции для вызова `transform (__ gnu_cxx:: __ normal_iterator < char *, std:: basic_string < char, std:: char_traits <char> , std:: allocator <char> gt;, __gnu_cxx:: __ normal_iterator < char *, std:: basic_string < char, std:: char_traits <char> , std:: allocator < char → > , std:: back_insert_iterator < std:: basic_string < char, std:: char_traits <char> , std:: allocator < char → < неразрешенный перегруженный тип функции > ) '

Что с ручным редактированием тоже разрешено:

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>)'

Что мне не хватает?

Ответ 1

Это не работает, потому что есть перегрузки std::toupper. Вы можете исправить это путем нажатия на требуемую перегрузку функции:

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

Ответ 2

Вам не хватает того, что С++ также добавляет новые функции toupper в <locale>, которые, вероятно, неявно включены одним из ваших других заголовков. Таким образом, в пространстве имен std:: существует несколько перегрузок, тогда как в глобальном пространстве имен существует только старая версия C функции.

Это говорит о том, что все еще похоже, что g++ должен иметь возможность выводить правильную перегрузку.