【问题标题】:Whats going on here with cctype?cctype 是怎么回事?
【发布时间】:2025-11-30 19:00:01
【问题描述】:

令我惊讶的是,以下代码可以编译:

#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, std::allocator >>, __gnu_cxx::__normal_iterator, std::allocator >>, std::back_insert_iterator<:basic_string std::char_traits>, std::allocator > >, 未解析的重载函数类型>)'

手动编辑也解决了:

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 提出这个问题。连我都想知道!
  • 对我来说看起来像一个 GCC 错误。我用VC编译没问题。
  • 啊,你只是忍不住对那些 g++ 输出微笑。他们是如此充满爱。
  • 我做了一些研究,认为它就像 std::toupper 和 ::toupper 在某种微妙的方式上不同,transform 无法处理,但我找不到任何东西。跨度>
  • Comeau Online 也编译代码,英特尔 C++ 也是如此

标签: c++ namespaces std


【解决方案1】:

它不起作用,因为有std::toupper 的重载。您可以通过强制转换为所需的函数重载来修复它:

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

【讨论】:

  • 这是一个更好的答案。在usenet 也发现了一些类似的讨论。
  • 好吧,如果我看到过,有一个论点是为 C++ 引入所有 cctype 函数的新版本(接受并返回字符)。这些函数接受并返回 int 以便它们可以处理 EOF 字符。
  • 还表明我应该学会阅读错误信息。它解释了确切的问题。
  • @GMan:我认为问题不在于应该做些什么才能让它发挥作用;毕竟::toupper 已经工作了。所以问题是,为什么std::toupper 不起作用?像我们明确提到的命名空间std一样,它应该不起作用吗?
  • @Nawaz:是的,通过导入::toupper&lt;locale&gt;template &lt;typename C&gt; C toupper(C c, const locale&amp; l);。仅指定 std::toupper 对参数无效,因为它也可能是。通过强制转换,它消除了一个过载。
【解决方案2】:

您错过了 C++ also&lt;locale&gt; 中添加了新的 toupper 函数,这可能包含在您的其他标题之一中。因此在std:: 命名空间中有多个重载,而在全局命名空间中只有旧的 C 版本的函数。

也就是说 g++ 似乎仍然能够推断出正确的重载。

【讨论】:

    最近更新 更多