【问题标题】:Error when trying to output element of a standard array that is a struct member尝试输出作为结构成员的标准数组的元素时出错
【发布时间】:2022-12-14 07:30:54
【问题描述】:

我正在尝试运行以下代码:

#include <iostream>
#include <array>

struct newperson {
    std::array<char, 20> name{};
    int age;
};

int main() {
    newperson nicolas = {
        "Nicolas",
        21
    };

    newperson martin = {
        "Martin",
        45
    };

    std::cout << nicolas.age << std::endl;
    std::cout << martin.name << std::endl;
    return 0;
}

,这是一个结构示例

我收到以下错误:

bast.cpp: In function 'int main()':
bast.cpp:21:19: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'std::array<char, 20>')
   21 |         std::cout << martin.name << std::endl;
      |         ~~~~~~~~~ ^~ ~~~~~~~~~~~
      |              |              |
      |              |              std::array<char, 20>
      |              std::ostream {aka std::basic_ostream<char>}

C:/msys64/mingw64/include/c++/12.2.0/ostream:754:5: error: no type named 'type' in 'struct std::enable_if<false, void>'

是否需要一些不同的语法?毕竟,我确实采用了一个现有示例并将 C 样式数组更改为标准数组。

如果我注释掉 Martin 行,我会得到以下信息:

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccClI6JG.o:bast.cpp:(.text+0x42): undefined reference to `std::ostream::operator<<(int)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccClI6JG.o:bast.cpp:(.text+0x54): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccClI6JG.o:bast.cpp:(.text+0x76): undefined reference to `std::ios_base::Init::~Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccClI6JG.o:bast.cpp:(.text+0xa9): undefined reference to `std::ios_base::Init::Init()'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccClI6JG.o:bast.cpp:(.rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_]+0x0): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccClI6JG.o:bast.cpp:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): undefined reference to `std::cout'
collect2.exe: error: ld returned 1 exit status

不过,这似乎是 mingw/msys2 的问题,因为它适用于 Godbolt 和 tio.run

【问题讨论】:

  • 这不是mingw的问题。 std::array&lt;char, 20&gt; 没有 &lt;&lt;。你为什么不使用 std::string ?
  • std::array&lt;T&gt; 不是T[] 的别名,它更像是一个安全(并且基本上同样有效)的包装器。如果你想得到指针,.data() 就可以了。
  • 顺便说一句,你的标题说你正在尝试打印数组的一个元素,那会起作用
  • @463035818_is_not_a_number 你是在谈论第一块错误消息吗?这可能与 mingw 无关,但肯定有问题:在尝试编译 this[(https://pst.moe/paste/lpsnaq) I get [this 时。如果我使用 g++ 而不是 gcc,我会得到 g++: fatal error: cannot execute 'cc1plus': spawn: No such file or directory compilation terminated. 有趣的是,这仅在我安装 mingw-w64-x86_64-gcc 之后才开始。当我使用 msys2 的 gcc 时,它运行良好。
  • 不,我只是指 std::cout &lt;&lt; martin.name &lt;&lt; std::endl;,这是一个错误,因为 std::array 没有 &lt;&lt;。另一方面,std::cout &lt;&lt; martin.name[0] &lt;&lt; std::endl; 可以打印数组的一个元素。我承认,我什至没有阅读您发布的错误消息

标签: c++ gcc g++ mingw-w64 msys2


【解决方案1】:

std::array 容器没有重载的 &lt;&lt;(流输出)运算符,无论元素类型如何。但是,该数组容器确实有一个 .data() 成员,它产生指向第一个元素的指针;在您的情况下,这将是一个 char* 并且输出 char* 的相关专业化(假设指向一个正确的以 null 结尾的字符串/数组)将执行您想要的操作:

std::cout << martin.name.data() << std::endl;

但是,正如在 cmets 中指出的那样,除非有特定原因导致结构中需要固定长度的数组,否则在这里使用 std::string 会好得多。

(如果您从为 .name 成员使用“C 风格”数组的代码改编此代码 – 即 char name[20]; – 那么 &lt;&lt; 将起作用,因为该数组名称将自动地“衰减”为指向其第一个元素的指针; std::array 不会发生这种情况。)

或者,尽管标准库提供的 array&lt;char, N&gt; 容器没有 &lt;&lt; ostream 重载,但您可以提供你自己的。这可以实现为函数模板(以便可以使用不同的数组大小),如下所示:

template <size_t N>
std::ostream& operator << (std::ostream& os, std::array<char, N> ArrChar)
{
    return os << ArrChar.data();
}

【讨论】:

  • 链接器错误与我在此处解决的问题无关。这几乎肯定意味着您需要将标准库作为输入添加到链接器:不确定如何为您的 mingw-64 系统执行此操作,但它大概类似于 -llibstc++ 开关。 This answer 可能有帮助。
  • -llibstdc++ 无效。我会尝试重新安装 MSYS2。也许应该选择 cygwin 或 wsl
  • @gps 我并不感到惊讶。这只是一种“猜测”。但是你的问题上的 cmets 可能更有帮助。此外,第二点似乎使您的帖子成为二问题。也许第二个问题应该成为第二个单独的问题。主要问题(我已经解决)独立为自己的问题。
  • @gps 这三个服务于不同的目的,并且没有一个从根本上被破坏。 MSYS2 生成 Windows 二进制文件。 Cygwin 生成带有 POSIX 仿真层的 Windows 二进制文件。 WSL 生成 Linux 二进制文件。
  • @gps 您应该根据要生成的二进制文件的种类来选择工具,然后让它工作。
猜你喜欢
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 2021-06-25
  • 2020-08-25
相关资源
最近更新 更多