0

I'm writing a function for a class that serializes structs representing packets to a single buffer, which is then sent to players in a multiplayer game. To keep this function as generic as possible, I though it would be a good idea to reserve a buffer for containing the structs and provide a template function that will construct the struct on the buffer and return a reference to it. Here is what I've tried...

template <typename T>
T& writePacket()
{
    auto addr = m_writeOffset;
    *m_writeOffset = T();
    m_writeOffset += sizeof(T);
    return *addr;
}

Where m_writeOffset is a u8* pointer to the next available byte.

I'm certain that returning a pointer to the location in the buffer where the struct lies would be much easier, however each of my packet struts contain a static byte for the header, which allows the clients to identify the packet types. Here are a few examples of some packets I might send:

typedef u8 packet_header;

#pragma pack(push, 1)
struct CP_AttackEntity
{
    static const packet_header header = 0;
    u16 targetUID;
};
#pragma pack(pop)

#pragma pack(push, 1)
struct CP_EntityMoved
{
    static const packet_header header = 3;
    u16 uid;
    Vec2<u16> pos;
};
#pragma pack(pop)

u8, u16, are just typedefs for uint8_t, etc.

I guess the reason why this isn't working comes from me not fully understanding how constructors work. When the packet is sent by the server or received by a client, the packets is entirely zeroed out. Can someone point me in the right direction? Thanks!

  • 1
    Do note that static members are not part of the memory of the class object. They exist in their own storage somewhere in the program. – NathanOliver Aug 09 '18 at 19:40
  • Can you give an [mcve] of the actual code that is causing all 0's? `*m_writeOffset = T();` looks to be undefined behavior and I'm curious how it even compiles. – NathanOliver Aug 09 '18 at 19:42
  • Is that the case? I thought that static would have meant that the variable in every instance of the struct would be initialized to a certain value. – Liam Bury Aug 09 '18 at 19:43
  • 1
    Nope. A static class variable has a name that is scooped to the class (so all objects of that type can access it), but is a single object shared by all instances off the class. Somewhere you should have a cpp file where you have `const packet_header CP_EntityMoved::header = 3;`. – NathanOliver Aug 09 '18 at 19:45
  • You want to run a Google search for "placement new". [You can start here, as a good example](https://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new). – Sam Varshavchik Aug 09 '18 at 19:52
  • Wow! That's exactly what I was looking for! I'll change my code to reflect both of your ideas and let you know how it works out. In addition, I could share the assembly code for my original function with NathanOliver – Liam Bury Aug 09 '18 at 20:25
  • Also, read up on [Plain old datatypes](https://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special). You could create a trivial constructor that initializes the header byte to your tag. – James Poag Aug 09 '18 at 20:29

0 Answers0