This code is incorrect since sockaddr
's size is arbitrary, and only meant to be used as a pointer to cast to a more derived type like sockaddr_in
or sockaddr_in6
.
You need the memcpy because you may need to copy padding bits, which mSockAddr = inSockAddr
doesn't do. You also don't know the size after the structure has been cast to const sockaddr&
.
A corrected version of the code would look like:
class SocketAddress
{
public:
SocketAddress(const sockaddr_storage& inSockAddrStorage, std::size_t addrLen) : size(addrLen)
{
std::memcpy(&mSockAddr, &inSockAddrStorage, size);
}
SocketAddress(const sockaddr& inSockAddr, std::size_t addrLen) : size(addrLen)
{
std::memcpy(&mSockAddr, &inSockAddr, size);
}
SocketAddress(const SocketAddress& other) : size(other.size)
{
std::memcpy(&mSockAddr, &other.sockAddr, size);
}
// Add overloads for common socket types
SocketAddress(const sockaddr_in& inSockAddrIn) : SocketAddress(reinterpret_cast<const sockaddr&>(inSockAddrIn), sizeof(sockaddr_in)) {}
SocketAddress(const sockaddr_in6& inSockAddrIn6) : SocketAddress(reinterpret_cast<const sockaddr&>(inSockAddrIn6), sizeof(sockaddr_in6)) {}
SocketAddress(const sockaddr_un& inSockAddrUn) : SocketAddress(reinterpret_cast<const sockaddr_un&>(inSockAddrUn), sizeof(sockaddr_un)) {}
// operator= for this class will work
SocketAddress& operator=(const SocketAddress& other) {
size = other.size;
std::memmove(&mSockAddr, &other.mSockAddr, size);
return *this;
}
private:
sockaddr_storage mSockAddr;
std::size_t size;
}