简体   繁体   English

跨编译单元的C ++增量类型ID

[英]c++ incremental type ID across compilation units

I need each derived class to have a unique ID, but the ID's need to be incremental. 我需要每个派生类具有唯一的ID,但是ID必须是增量的。 Here is my current implementation: 这是我当前的实现:

//component.cpp
class ComponentId
{
public:
    ComponentId();


    static int nextId;
    int id;
};

template<class T>
class Component {
public:
    static const ComponentId componentId;
};

template<class T>
const ComponentId Component<T, chunkSize>::componentId;

///component.cpp
int ComponentId::nextId = 0;

ComponentId::ComponentId() : id(nextId++)
{
}

//IN static library a
struct compA : public Component<compA> {

}

//In static library b
struct compB : public Component<compB> {

}

//in main.cpp
#include <component.h>
#include <compA.h>
#include <compB.h>
std::cout << compA::componentId.id << std::endl;
std::cout << compB::componentId.id << std::endl;

This works fine in all my unit tests but doesn't seem to work as intended when using multiple compilation units or across static libraries. 这在我所有的单元测试中都可以正常工作,但在使用多个编译单元或跨静态库时似乎无法按预期工作。 The ID's are reused in different libraries. ID在不同的库中重复使用。 One library may have id's 0,1,2 and 3, but another library will also have classes with IDs 0 and 1. My guess is that the nextid field isn't being shared. 一个库可能具有id的0、1、2和3,但是另一个库也将具有ID为0和1的类。我的猜测是nextid字段没有被共享。

I have also tried to use the extern keyword but It seemed to produce the same issue. 我也尝试过使用extern关键字,但似乎会产生相同的问题。 I have also tried to make a static getId function in hopes to do initialization on first use, but no such luck. 我也尝试过制作一个静态的getId函数,希望在首次使用时进行初始化,但是没有这种运气。

I really need the IDs to be 'tight', as in 1,2,3,4,5, rather than 67, 80, 123, 1, 4. 我真的需要ID是“紧密的”,例如1,2,3,4,5,而不是67、80、123、1、4。

Any ideas? 有任何想法吗?

Assuming that you want a single int instance shared across multiple TUs, I think that using an inline function that returns a reference to a static int should do the trick: 假设您要在多个TU之间共享一个int实例,我认为使用inline函数返回对static int的引用应该可以解决问题:

// counter.hpp
namespace detail 
{
    inline int& getCounter()
    {
        static int result{0};
        return result;
    }
}

inline int nextId()
{
    return detail::getCounter()++;
}

// component.cpp
ComponentId::ComponentId() : id(nextId())
{
}

Nevertheless, this feels brittle and prone to errors, especially if you're aiming to rely on your ID for serialization/deserialization. 尽管如此,这感觉很脆弱并且容易出错,尤其是在您要依靠ID进行序列化/反序列化的情况下。 If you know all the types of your components at compile-time, I suggest using a typelist. 如果您知道编译时组件的所有类型,建议使用类型列表。 Eg 例如

using components = typelist<
    Component0,
    Component1,
    Component2,
    Component3
>;

Otherwise, if you only know your components types at run-time, provide some sort of registry that allows users to register/unregister types in a controlled manner. 否则,如果仅在运行时知道组件类型,则提供某种注册表,允许用户以受控方式注册/取消注册类型。

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

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