OutpostUniverse / OP2Utility

C++ library for working with Outpost 2 related files and tasks.
MIT License
4 stars 0 forks source link

Add serializer for vector of non-trivial types #281

Open DanRStevens opened 5 years ago

DanRStevens commented 5 years ago

Work-in-progress: This is a quick attempt that doesn't account for forwarding of template parameters. Care will need to be taken to properly forward types to custom serialization methods.

This requires the guard update in PR #280 in order to resolve calls to the new method.

Current output of the test code in Issue #276 is:

hexdump -C Test.out 
00000000  53 68 6f 72 74 20 73 74  72 69 6e 67 41 20 63 6f  |Short stringA co|
00000010  6e 73 69 64 65 72 61 62  6c 79 20 6c 6f 6e 67 65  |nsiderably longe|
00000020  72 20 73 74 72 69 6e 67                           |r string|
00000028

As can be seen, the strings are not length prefixed, and neither is the vector data as a whole. Forwarding of template type parameters will be needed to properly accomplish this.

DanRStevens commented 5 years ago

A single level of template parameters works quite easily with the above code.

Changing the test code to use:

writer.Write<int>(data);  // **

Produces the following binary output:

hexdump -C Test.out 
00000000  02 00 00 00 53 68 6f 72  74 20 73 74 72 69 6e 67  |....Short string|
00000010  41 20 63 6f 6e 73 69 64  65 72 61 62 6c 79 20 6c  |A considerably l|
00000020  6f 6e 67 65 72 20 73 74  72 69 6e 67              |onger string|
0000002c

Here the vector has a length prefix written to the data. The individual strings do not. There it is calling the non-length-type prefixed version of the std::string serializer, which writes the string without a length prefix. It may be possible to use parameter packs to pass on extra type arguments:

template<typename T, typename A, typename ... Args>

The call would then be to:

Write<Args...>(element);   // Call custom serializer

However, the T and A arguments seem to get in the way. I tried moving ... Args up front, but that also didn't work as that created ambiguity with the other template methods.

Indeed, how do you differentiate between writing a vector with a length prefix, and writing a vector with no length prefix, but including a length prefix on the strings written:

// Ambiguous
writer.Write<int>(vector);  // Vector is length prefixed, strings are not
writer.Write<char>(vector);  // Vector is not length prefixed, but strings are

It's a little more clear if both are length prefixed, but that might not always be desirable:

// Probably still ambiguous due to T and A parameters
writer.Write<int, char>(vector);  // Vector is int length prefixed, strings are char length prefixed

Edit: This looks promising: https://stackoverflow.com/questions/37329826/can-the-container-type-be-deduced-in-variadic-templates/37330016

DanRStevens commented 3 years ago

This branch was getting really stale. I squashed the commits together, as they were experimental and fixing up earlier commits in the branch. I then rebased the branch onto current code.

Will still need to revisit this. I've lost context on it, though it seems there are good notes in the PR thread and associated issue.