c ++编译单元的增量类型ID

时间:2018-03-19 13:19:26

标签: c++ static initialization unique identifier

我需要每个派生类都有一个唯一的ID,但ID必须是增量的。 这是我目前的实施:

//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;

这在我的所有单元测试中都能正常工作,但在使用多个编译单元或跨静态库时似乎没有按预期工作。 ID在不同的库中重复使用。一个库可能具有id 0,1,2和3,但是另一个库也将具有ID为0和1的类。 我的猜测是nextid字段没有被共享。

我也试过使用extern关键字,但似乎产生了同样的问题。 我还尝试创建一个静态getId函数,希望在第一次使用时进行初始化,但没有这样的运气。

我真的需要这些ID是紧密的,如1,2,3,4,5,而不是67,80,123,1,4。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

假设您希望在多个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())
{
}

然而,这感觉很脆弱并且容易出错,特别是如果您的目标是依靠您的ID进行序列化/反序列化。如果您在编译时了解组件的所有类型,我建议使用类型列表。 E.g。

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

否则,如果您只在运行时知道组件类型,请提供某种允许用户以受控方式注册/取消注册类型的注册表。