memcpy() is just fine, if you know what you're doing. However, memcpy() doesn't work for copying into storage for an object that's not POD (that has virtual functions, for example).
Note that a template with type "T" is not runtime polymorphism; it's static polymorphism. Also, a switch() is not runtime polymorphism. Virtual functions are what are used in C++ to implement runtime polymorphism.
If you want to use polymorphism to create packets, then you can for example use a class factory pattern:
class Packet { public: virtual bool Unpack(void const *&data, size_t size) = 0; virtual bool Pack(void *&data, size_t size) = 0; virtual void Dispatch(PacketDispatchTarget *t) = 0;};template<typename T> class PacketBase : Packet{ public: PacketBase() {} PacketFactory *Factory() { return PacketFactory<T>::instance_; }};class PacketFactoryBase { public: PacketFactoryBase(int id) { assert(Factories()[id] == NULL); Factories()[id] = this; } static PacketFactory *PacketFactoryForId(int id) { if (Factories().find(id) == Factories().end()) return 0; return Factories()[id]; } protected: int id_; virtual Packet *MakePacketBase() = 0; static map<int, PacketFactory *> &Factories() { static map<int, PacketFactory *> it; return it; }};template<typename T, int Id> class PacketFactory { public: PacketFactory() : PacketFactoryBase(Id) { instance_ = this; } enum { ID = Id; } static PacketFactory *instance_; T *MakePacket() { return static_cast<T *>(PacketFactoryBase::MakePacketBase()); }; protected: Packet *MakePacket() { return new T(); }}class SignInPacket : public PacketBase<SignInPacket> { public: SignInPacket(char const *name, char const *password) : name_(name), password_(password) {} bool Unpack(void const *&data, size_t &size) { return unpack_string(data, size, name_) && unpack_string(data, size, password_); } bool Pack(void *&data, size_t &size) { return pack_string(data, size, name_) && pack_string(data, size, password_); } void Dispatch(PacketDispatchTarget *t) { ... do whatever ... } std::string name_; std::string password_;};... more packet types ...PacketFactory<SignInPacket, 1> signInFactory;PacketFactory<SayHelloPacket, 2> sayHelloFactory;...
After you have set this up, you can use both static (compile-time) and dynamic (runtime) polymorphism.
When you want to pack up a packet to a byte array, put an integer into the byte array for the ID of the packet, and then call Packet->Pack(data, size) to put it into the array. On the other end, read the integer out and call PacketFactoryBase::PacketFactoryForId() to get the appropriate packet factory; call that to create a new packet, and call Unpack(data, size) on that packet to re-inflate it from data. You can then, for example, dispatch the packet to a dispatch target that you define (or do whatever else you want with it).
This is obviously just a loose illustration that won't quite compile, but it should hopefully be clear enough to show how you can do packet creation, sending, receiving and dispatching entirely without "if" or "switch" statements, which is what using polymorphism is all about!
[Edited by - hplus0603 on January 1, 2009 11:59:28 AM]