Home > Mobile >  Error when trying to output element of a standard array that is a struct member
Error when trying to output element of a standard array that is a struct member

Time:10-22

I'm trying to run the following code:

#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;
}

, which is a struct example

I get the following errors:

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

Is some different syntax required? I did take an existing example and change the C-style array to a standard one, after all.

And if I comment out the Martin lines, I get the following:

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

That seems to be a problem with mingw/msys2, though, because it works with Godbolt and tio.run

CodePudding user response:

There is no overloaded << (stream output) operator for the std::array container, whatever the element type. However, that array container does have a .data() member, which yields a pointer to the first element; in your case, that will be a char* and the relevant specialisation for outputting a char* (assuming that points to a properly null-terminated string/array) will do what you want:

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

But, as pointed out in the comments, you would be far better off using a std::string, here, unless there is a specific reason why you need a fixed-length array in your structures.

(If you adapted this from code that used a "C-style" array for the .name member – i.e. char name[20]; – then the << would work because that array name will automatically 'decay' into a pointer to its first element; this doesn't happen for std::array.)

Alternatively, although there is no << ostream overload for the array<char, N> container provided by the Standard Library, you could provide your own. This can be implemented as a function template (so that different array sizes could be used), like this:

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