Issue #77 Move mixin classes to separate files

By separating them from unrelated code, their dependents
can use them without depending on unrelated code, which
in turn helps to reduce cyclic dependencies.
This commit is contained in:
Mat Sutcliffe
2020-08-25 23:31:23 +01:00
parent 4a6d94b6d4
commit b80114213d
129 changed files with 1207 additions and 969 deletions

View File

@@ -11,85 +11,8 @@
#ifndef BLACKMISC_DATASTREAM_H
#define BLACKMISC_DATASTREAM_H
#include "blackmisc/typetraits.h"
#include <QDataStream>
namespace BlackMisc
{
class CEmpty;
namespace Mixin
{
/*!
* CRTP class template to generate non-member QDataStream streaming operators.
*
* \tparam Derived Must implement public methods marshalToDataStream(QDataStream &) and unmarshalFromDataStream(QDataStream &).
*/
template <class Derived>
class DataStreamOperators
{
public:
//! Marshal a value to a QDataStream.
friend QDataStream &operator <<(QDataStream &stream, const Derived &value)
{
value.marshalToDataStream(stream);
return stream;
}
//! Unmarshal a value from a QDataStream.
friend QDataStream &operator >>(QDataStream &stream, Derived &value)
{
value.unmarshalFromDataStream(stream);
return stream;
}
};
/*!
* CRTP class template to generate QDataStream marshalling methods using CMetaClass.
*
* \see BLACKMISC_DECLARE_USING_MIXIN_DATASTREAM
*/
template <class Derived>
class DataStreamByMetaClass : public DataStreamOperators<Derived>
{
public:
//! Marshal a value to a QDataStream.
void marshalToDataStream(QDataStream &stream) const
{
baseMarshal(static_cast<const TBaseOfT<Derived> *>(derived()), stream);
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
meta.forEachMember([ &, this ](auto member) { stream << member.in(*this->derived()); });
}
//! Unmarshal a value from a QDataStream.
void unmarshalFromDataStream(QDataStream &stream)
{
baseUnmarshal(static_cast<TBaseOfT<Derived> *>(derived()), stream);
constexpr auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
meta.forEachMember([ &, this ](auto member) { stream >> member.in(*this->derived()); });
}
private:
const Derived *derived() const { return static_cast<const Derived *>(this); }
Derived *derived() { return static_cast<Derived *>(this); }
template <typename T> static void baseMarshal(const T *base, QDataStream &stream) { base->marshalToDataStream(stream); }
template <typename T> static void baseUnmarshal(T *base, QDataStream &stream) { base->unmarshalFromDataStream(stream); }
static void baseMarshal(const void *, QDataStream &) {}
static void baseUnmarshal(void *, QDataStream &) {}
static void baseMarshal(const CEmpty *, QDataStream &) {}
static void baseUnmarshal(CEmpty *, QDataStream &) {}
};
/*!
* When a derived class and a base class both inherit from Mixin::DataStreamByMetaClass,
* the derived class uses this macro to disambiguate the inherited members.
*/
# define BLACKMISC_DECLARE_USING_MIXIN_DATASTREAM(DERIVED) \
using ::BlackMisc::Mixin::DataStreamByMetaClass<DERIVED>::marshalToDataStream; \
using ::BlackMisc::Mixin::DataStreamByMetaClass<DERIVED>::unmarshalFromDataStream;
}
}
#include <utility>
/*!
* Operator for marshalling pairs with QDataStream.