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

标签 c++ c++11 templates macros

背景

我正在修改 C++ 中的多态序列化和反序列化。 为此,我使用静态 map :[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 在他的回答中提到的匿名命名空间可以使用。不幸的是,不能在翻译单元中多次使用宏是一个缺点。例如,对于仅 header 类型。

最佳答案

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

/// 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__ 宏标记为您的对象创建唯一的名称 - 只要您不必在其他地方引用它。还有其他的,列表可以查here .

关于c++ - 为模板类静态实例生成有效标识符的宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42482894/

相关文章:

c++ - VC++ 2008 编译问题与 boost

c++ - 有没有办法使用 C++ 堆栈容器设置堆栈大小?

c++ - 没有调用复制构造函数

采用 float 或 double 的 C++ 模板函数

c++ - 类 - 命名空间和模板成员函数特化

c++ - 检查数字是否为回文

c++ - 模板类中的友元运算符声明

c++ - 类 x86 系统的 C++11 内存屏障是如何实现的?

C++ - 模板参数推导/替换失败

c++ - 容器模板参数 std::map 或 std::vector