我如何解释这个c++错误?

How can I interpret this C++ error

本文关键字:c++ 错误 解释 何解释      更新时间:2023-10-16

我有这行代码(行是字符串类型):

char* p = line.data;

在你回复之前,我已经知道我做错了什么,我需要在末尾加上括号。我想问你的是我应该如何解释我得到的错误,以供将来参考:

error: cannot convert ‘std::basic_string<_CharT, _Traits, _Alloc>::data<char, std::char_traits<char>, std::allocator<char> >’ from type ‘const char* (std::basic_string<char>::)()const noexcept (true)’ to type ‘char*’

所以首先我必须问,这可能更令人困惑吗?你们这些c++开发人员究竟是怎么处理这样的事情的?感谢上帝赐予我们更高层次的语言,对吧?好吧,所有这些问题都只是反问句。

这个错误我已经读了十几遍了。我还查看了字符串数据方法文档,它确实说它返回一个char*。所以我对以下内容感到困惑:

  1. 指的是:

    basic_string<_CharT, _Traits, _Alloc>
    

根据basic_string文档,它有一个模板参数,但这个错误似乎说有三个:_CharT, _Traits和_Alloc。为什么这个基本字符串有三个模板参数,而文档说它只有一个?我想我不明白如何解释那个文档或那个错误信息。

  1. 那么看起来数据部分也有模板参数,

    ...::data<char, std::char_traits<char>, std::allocator<char> >
    

但是根据'data'方法文档,它是这样定义的:

    const char* data() const noexcept;

我在定义中没有看到任何模板参数。为什么错误消息显示所有这些模板参数?

  1. 然后它变得更混乱,错误信息说它试图从类型转换:

    const char* (std::basic_string<char>::)()const noexcept (true)
    

所以我认为这是c++描述函数类型的方式,对吗?为什么它以括号中的true结尾?

所以我想我主要是想弄清楚为什么c++异常有所有这些奇怪的模板参数,我没有在任何文档中看到。

您提供的错误消息似乎被错误地引用了(或被解析器弄乱了)。GCC生成以下

error: cannot convert ‘std::basic_string<_CharT, _Traits, _Alloc>::data<char, std::char_traits<char>, std::allocator<char> >’ from type ‘const char* (std::basic_string<char>::)()const’ to type ‘char*’
  1. 我不知道什么文档告诉你std::basic_string只有一个模板参数。

  2. 类本身和类的成员函数是独立的模板。因此,basic_string是一个模板类,basic_string::data()是一个单独的模板函数。错误信息给出了该data模板函数的全名

    std::basic_string<_CharT, _Traits, _Alloc>::data<char, std::char_traits<char>, std::allocator<char> >
    

    第一部分

    std::basic_string<_CharT, _Traits, _Alloc>
    

    只是类名,而其余部分是模板函数,函数名后面列出了实际的模板参数。这绝不是引用此模板的完美方式。最有可能的是它从编译器的内部工作方式派生出来的

  3. 从语言的角度来看,"从函数类型强制转换"部分没有逻辑。从c++语言的角度来看,line.data根本不是一个有效的表达式。因此它没有类型。然而,显然GCC编译器的内部工作将该组合视为成员函数类型的表达式。错误消息实际上显示该类型为

    const char* (std::basic_string<char>::)()const
    

    其他编译器也知道这样做。同样,这只是编译器的内部机制。

在实践中,c++程序员处理这个问题的方法是重复同样的错误足够多次,这样他们通常可以识别错误消息的"形状",而不必详细阅读它。

通常,当我在源代码行中遇到错误时,我所做的是查看我是否做了一些愚蠢的事情(不详细阅读错误消息)。只有当失败并且我看不到它时,我才会读取错误消息并查看编译器在抱怨什么。有时它仍然是不可理解的,我不得不回去寻找一些愚蠢的东西。在极端情况下,这种情况可能会发生几次,然后我才发现。