EDIT: I seem to have misunderstood your question. If you want to transmit data to a remote machine, i.e. over a network or something you need a serialization library like Boost.Serialization: http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html. Converting your types, especially non trivial types, to a stream of bytes and then converting them back again is not an easy task. I would go with boost.
My original answer which only works to send data around inside a process but not outside the process:
If you don't want to use boost.any or boost.variant you can roll your own using the excelent non intrusive polymorphism pattern from Sean Parent:
class PacketData{
struct Context {
virtual ~Context() = default;
};
template<typename T>
struct Instance : Context {
Instance(T&& t):data_{std::move(t)}{
}
T data_;
};
std::unique_ptr<Context> self_;
public:
template<typename T>
PacketData(T in):self_{new Instance<T>{std::move(in)}}{}
//move is easy, copy is harder ;)
template<typename T>
bool isA(){
return dynamic_cast<Instance<T>*>(self_.get()) != nullptr;
}
template<typename T>
T& asA(){
if(!isA<T>()){
throw std::runtime_error("bad cast or something");
}
return dynamic_cast<Instance<T>*>(self_.get())->data_;
}
};
After making this variant class the rest should be easy:
using Packet = std::vector<PacketData>;
Packet packet;
packet.push_back(4);
packet.push_back(4.4f);
packet.push_back(std::string{"test"});
int i = packet[0].asA<int>();
float f = packet[1].asA<float>();
std::string s = packet[2].asA<std::string>();
Here is a live example: http://ideone.com/U7rmOL
If you want speed you could get around the heap allocation by puting a stack allocator in the PacketData class which is big enough to hold the usual data sizes. See http://home.roadrunner.com/~hinnant/stack_alloc.html