繁体   English   中英

宏为模板类静态实例生成有效的标识符

[英]Macro generating a valid identifier for template-class static instance

背景

我正在修补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在他的回答中提到的,可以使用匿名名称空间 不幸的是,不能在翻译单元中多次使用宏是一个缺点。 例如,仅用于标头类型。

一种部分解决方案是始终使用相同的名称,但将其包装在未命名的名称空间中。 这将只允许您为每个翻译单元注册一种类型,但这也许就足够了。

/// Macro that registers the type at compile-time using a static factory instance
#define REGISTER_TYPE(T)                                         \
    namespace {                                                  \
        static SerializableFactory<T> serial_global_factory(#T); \
    }

否则,您可以使用__LINE____FILE__宏标记为您的对象创建一个唯一的名称-只要您不必在其他任何地方引用它即可。 还有其他一些,可以在这里找到列表。

我有一个啊哈! 来自@WF的评论,@ Svalorzen答案和答案的启发。 我相信这是一个聪明的把戏,没有其他选择的缺点。


解决方案:使用未命名/匿名名称空间并将 __LINE__添加到标识符应始终提供唯一标识符(除非在同一行两次使用该宏)。


外观如下:

#define MERGE(A, B) A##B
#define CREATE_UNIQUE_IDENTIFIER(line) MERGE(unique_identifier_on_line_, line)
/// UNIQUE_IDENTIFIER generates identifiers like:
/// "unique_identifier_on_line_" + line_number
#define UNIQUE_IDENTIFIER CREATE_UNIQUE_IDENTIFIER(__LINE__)
/// Macro that registers the type at compile-time using a static factory instance
#define REGISTER_TYPE(T)                                                   \
    namespace                                                              \
    {                                                                      \
    static SerializableFactory<T> UNIQUE_IDENTIFIER(#T);                   \
    }

尝试将类型定义为单个名称并使用名称:

typedef ArbitraryClass<int> ArbitraryClass_int_;
REGISTER_TYPE(ArbitraryClass_int_);

您也可以尝试将其放在哈希映射中,其中的键是类型名。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM