CAF is currently littered with redundant code to enable serialization and
string conversion for its custom types.
Current Approach
Currently, CAF requires serializable types to provide a free function
serialize. Any type convertible to string is required to provide a free
to_string function:
/// Stores a flow-control configuration.
struct named_actor_config {
atom_value strategy;
size_t low_watermark;
size_t max_pending;
};
template <class Processor>
void serialize(Processor& proc, named_actor_config& x, const unsigned int) {
proc & x.strategy;
proc & x.low_watermark;
proc & x.max_pending;
}
inline std::string to_string(const named_actor_config& x) {
return "named_actor_config"
+ deep_to_string_as_tuple(x.strategy, x.low_watermark, x.max_pending);
}
Both of these function inspect an object and expose state to the caller.
Generalized Approach
When extending the current system with new type concepts such as parseable,
developers are required to implement one free function per concept per type.
This clearly does not scale. This proposal suggests a general-purpose reflect
function that allows a "mirror" object to visit state as well as meta
information. Different mirrors can ignore meta information in contexts where
they are not required. For example, a serializer can ignore meta information
that is always equal for all instances of an object such as class names.
The reflect function replacing serialize and to_string from the example
above would look as follows.
template <class Mirror>
void reflect(Mirror& mirror, named_actor_config& x, const unsigned int) {
mirror & meta::type_name("named_actor_config");
mirror & x.strategy;
mirror & x.low_watermark;
mirror & x.max_pending;
}
With:
namespace meta {
struct type_name { const char* value; };
} // namespace meta
Serializers should still fall back to serialize functions and prefer
serialize over reflect. First, to guarantee backward-compatibility as well
as compatibility to other frameworks such as Boost.Serialize. Second, because
some types cannot provide a general-purpose reflect function that is suitable
for serialization (for example actors).
Open Questions
- What additional meta information do we need to support?
- Can/should we inject
std::ostream<< operators for types supporting reflect
CAF is currently littered with redundant code to enable serialization and
string conversion for its custom types.
Current Approach
Currently, CAF requires serializable types to provide a free function
serialize. Any type convertible to string is required to provide a freeto_stringfunction:Both of these function inspect an object and expose state to the caller.
Generalized Approach
When extending the current system with new type concepts such as
parseable,developers are required to implement one free function per concept per type.
This clearly does not scale. This proposal suggests a general-purpose
reflectfunction that allows a "mirror" object to visit state as well as meta
information. Different mirrors can ignore meta information in contexts where
they are not required. For example, a serializer can ignore meta information
that is always equal for all instances of an object such as class names.
The
reflectfunction replacingserializeandto_stringfrom the exampleabove would look as follows.
With:
Serializers should still fall back to
serializefunctions and preferserializeoverreflect. First, to guarantee backward-compatibility as wellas compatibility to other frameworks such as Boost.Serialize. Second, because
some types cannot provide a general-purpose
reflectfunction that is suitablefor serialization (for example actors).
Open Questions
std::ostream<<operators for types supportingreflect