【发布时间】:2017-02-27 10:07:44
【问题描述】:
背景
我正在修改 C++ 中的多态序列化和反序列化。
为此,我使用静态地图:[type id-string] -> [type factory function]。
每种类型都必须在此映射中注册,我想在编译时进行。
方法
天真的方法是:
/// Creates a concrete serializable type provided as a template parameter
template <typename T>
ISerializable* createSerializable() { return new T; }
/// Factory that registers a serializable type T
template <typename T>
struct SerializableFactory
{
SerializableFactory(const char* type_name)
{
// registerType adds a type_name->factory_function entry to the map
registerType(type_name, createSerializable<T>);
}
};
注册类型是通过宏来完成的:
/// Macro that registers the type at compile-time using a static factory instance
#define REGISTER_TYPE(T) \
static SerializableFactory<T> global_##T##Factory(#T);
例如REGISTER_TYPE(ArbitraryClass)会变成:
static SerializableFactory<ArbitraryClass>
global_ArbitraryClassFactory("ArbitraryClass");
问题
很遗憾,这不适用于ArbitraryClass<int>,因为<、> 不允许在标识符中使用。
问题
有没有很好的解决方法来实现以这种方式注册任意模板类型?
替代品
我考虑了以下替代方案(每个都有缺点):
- 在运行时注册类型:看起来不那么优雅,需要序列化用户更多的努力;
- RTTI:需要启用 RTTI,不保证不同类型总是有不同的哈希/名称(当然不太可能,但仍然如此);
- 要求用户提供类型别名或别名:不太优雅,序列化用户需要付出更多努力
更新:
- 正如@Svalorzen 在他的回答中提到的那样,匿名命名空间 可以使用。不幸的是,不能在翻译单元中多次使用宏是一个缺点。例如,对于仅标题类型。
【问题讨论】:
-
您是否考虑过使用
__COUNTER__宏而不是T来生成工厂实例唯一名称?我知道这不是标准的,但绝对可以在这里解决问题...... -
@W.F.不,我没有。谢谢你的建议。是的,不标准是一个缺点。如果没有副作用,并且被三大编译器支持,谁知道:)
标签: c++ c++11 templates macros