Commit 1c873398 authored by Jason Rhinelander's avatar Jason Rhinelander

Serializer: add `size = 0` member for variable size items

This makes it easier to write code that is conditionally fixed-size,
such as std::pair<A, B> which is fixed iff both A and B are fixed,
which is more easily determined via a constexpr than SFINAE on member
existance.
parent 22596773
......@@ -224,8 +224,8 @@ public:
* reference an actual, non-const storage location that remains valid.
*
* The added type T must have a eris::serialize::serializer<T> implementation, which must be a
* fixed size (exposed as ::size). Primitive floating point and integer types will work (with
* the default serializer<T> implementation).
* fixed size (exposed as non-zero static constexpr size_t ::size). Primitive floating point
* and integer types will work (with the default serializer<T> implementation).
*
* Subclasses should call this method during configureHeaderFields() to ensure that all fields
* are set up for the detected file version.
......@@ -239,6 +239,7 @@ public:
template <typename T>
typename std::enable_if<not std::is_const<T>::value>::type
addHeaderField(T &store) {
static_assert(serializer<T>::size > 0, "addHeaderField requires a fixed-size type");
if (header_fields_done_) throw std::logic_error("Cannot add header fields after the header has been read or written");
auto s = std::make_shared<serializer<T>>(store);
app_fields_.emplace_back(s);
......@@ -363,6 +364,7 @@ public:
*/
template <typename T>
uint64_t blockListCreate(uint16_t elements_per_block = 511) {
static_assert(serializer<T>::size > 0, "blockListCreate requires a fixed-size type");
static_assert(serializer<T>::size <= std::numeric_limits<uint8_t>::max(), "Block element size must be <= 255");
return blockListCreate(serializer<T>::size, elements_per_block);
}
......
......@@ -23,9 +23,10 @@ namespace eris { namespace serialize {
* across architectures with more fundamental differences (e.g. different floating point
* representations).
*
* If the serialized type has a constant size, it should be exposed by declaring a static `size`
* member indicating the size; this will allow it to be used in places such as
* Serializer::addHeaderField, which only allow constant-sized serialization values.
* If the serialized type has a constant size, it should be exposed by declaring a static `size_t
* size` member indicating the size; this will allow it to be used in places such as
* Serializer::addHeaderField, which only allow constant-sized serialization values. To explicitly
* indicate a non-constant size, a `size` field can be declared with a value of 0.
*/
template <typename T, typename Sfinae = void>
class serializer;
......@@ -43,6 +44,10 @@ public:
/// Virtual destructor.
virtual ~serializer_base() = default;
/// The default size, 0, which indicates non-constant size. Constant-size serializers should
/// mask this with their own non-zero value.
static constexpr size_t size = 0;
/// Replaces the current value with a value read from the given input stream.
virtual void load_from(std::istream &is) = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment