Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Odd error message when trying to cast a structure in C++

Using C++ on Linux, I just rather stupidly wrote this:

struct in_addr ip_addr = ((struct sockaddr_in)socket_addr).sin_addr;

Instead of the intended:

struct in_addr ip_addr = ((struct sockaddr_in*)&socket_addr)->sin_addr;

Giving me this error:

"error: no matching function for call to ‘sockaddr_in::sockaddr_in(sockaddr&)"

I know why I have the error (I was trying to cast a structure), but I don't understand why the error message says what it does. Can someone please explain?

like image 573
Ed King Avatar asked May 17 '17 09:05

Ed King


3 Answers

When the compiler encounters a C-style cast, it tries to interpret it as one or two C++-style casts, in the following order:

  • const_cast<new_type>(expression)
  • static_cast<new_type>(expression)
  • static_cast (with extensions) followed by const_cast
  • reinterpret_cast<new_type>(expression)
  • reinterpret_cast followed by const_cast

The first choice that satisfies the requirements of the respective cast operator is selected, even if it cannot be compiled.

In your case, static_cast<sockaddr_in>(socket_addr) is selected. This is direct initialization, so the compiler looks for, and does not find, a constructor that takes a const reference to the object being cast.

Note that the same conversion does not trigger an error when applied to pointers, because language has built-in conversions between pointers of different types.

like image 137
Sergey Kalinichenko Avatar answered Nov 14 '22 03:11

Sergey Kalinichenko


When doing the cast on the type (and not the pointer), the compiler try to call the constructor of sockaddr_in that take a object of the same type as socket_addr. Since that constructor doesn't exists, the compiler throw the error you showed.

like image 28
nefas Avatar answered Nov 14 '22 05:11

nefas


Because that's how casts work — they convert an A to a B, and (unless B is a pointer or a reference) that requires invoking a conversion operator or a constructor. The compiler is trying to find a constructor to create a sockaddr_in from a sockaddr; none exists, hence the error.

It can't guess that you really meant to attempt a conversion to something else instead.

I've found that a large part of becoming a productive C++ programmer is learning the art of taking these compiler errors and using them to heuristically determine what the actual problem likely is. ;)

like image 34
Lightness Races in Orbit Avatar answered Nov 14 '22 05:11

Lightness Races in Orbit