如何为全局类型设置一个静态计数器?
How to have a static counter for global types?
我想要一个静态计数器,每次我创建另一种类型时它都会增加,class。这是我尝试过的:
template <typename Type>
class Sequential_ID_Dispenser
{public:
static inline int nextDispensed = 0;
static int getID() { return nextDispensed++; }
};
struct DummyTypeForComponentIDs {}; // So that the same type is passed to getID()
template <typename T>
struct Component {
static inline int componentTypeID = Sequential_ID_Dispenser<DummyTypeForComponentIDs>::getID();
};
// The reason I've made it inherit like this is so that any time I add a new Component type/struct it'll automatically get an ID for that type
struct Hat : Component<Hat> {};
struct Tie : Component<Tie> {};
int main()
{
int id = Hat::componentTypeID; // = 0
id = Tie::componentTypeID; // = 1
}
这行得通。但是我想有一个选项可以轻松地从任何其他组件继承,但它不是这样工作的,例如:
template <typename T>
struct Component {
static inline int componentTypeID = Sequential_ID_Dispenser<DummyTypeForComponentIDs>::getID();
};
struct Hat : Component<Hat> {};
struct Tie : Component<Tie> {};
struct BlueHat : Hat {};
int main()
{
int id = Hat::componentTypeID; // = 0
id = Tie::componentTypeID; // = 1
id = BlueHat::componentTypeID; // = 0, gets the same number as struct Hat : Component<Hat>{}
}
有什么好的解决办法吗?我想理想地定义任何新结构而不将参数传递给基本构造函数。我意识到我为此使用了 CRTP,这正是我为使其工作所做的,但必须有更简单的方法,对吗?
编辑:实际上我很惊讶解决方案并不简单,我想要的只是为我在全局命名空间中创建的每个 class 获取一个新 ID,我想要么是编译时间要么运行时间。
我找不到一种简单的方法来扩展您当前的解决方案来执行此操作,除非您想开始在每个继承声明符上抛出 virtual
,并记住每次都这样做.
无论如何,“计数类型”似乎有点反模式。通过 typeid
.
,我们已经有了唯一的类型标识符
如果你真的需要一个 int
,你可以让一些管理器 class 接受一个 std::type_info
并给你一个对该类型唯一的 int
,可能使用一张为其供电的地图。但是,如果您可以将 std::type_info
存储在第一位,那就更好了。缺点是此信息将无法静态使用(即“在编译时”)。
您不需要继承类型上的(运行时)计数器。
您甚至可以使用模板变量 (C++14):
std::size_t getId()
{
static std::size_t counter = 0;
return counter++;
}
template <typename T>
std::size_t Id = getId();
Demo.
我想要一个静态计数器,每次我创建另一种类型时它都会增加,class。这是我尝试过的:
template <typename Type>
class Sequential_ID_Dispenser
{public:
static inline int nextDispensed = 0;
static int getID() { return nextDispensed++; }
};
struct DummyTypeForComponentIDs {}; // So that the same type is passed to getID()
template <typename T>
struct Component {
static inline int componentTypeID = Sequential_ID_Dispenser<DummyTypeForComponentIDs>::getID();
};
// The reason I've made it inherit like this is so that any time I add a new Component type/struct it'll automatically get an ID for that type
struct Hat : Component<Hat> {};
struct Tie : Component<Tie> {};
int main()
{
int id = Hat::componentTypeID; // = 0
id = Tie::componentTypeID; // = 1
}
这行得通。但是我想有一个选项可以轻松地从任何其他组件继承,但它不是这样工作的,例如:
template <typename T>
struct Component {
static inline int componentTypeID = Sequential_ID_Dispenser<DummyTypeForComponentIDs>::getID();
};
struct Hat : Component<Hat> {};
struct Tie : Component<Tie> {};
struct BlueHat : Hat {};
int main()
{
int id = Hat::componentTypeID; // = 0
id = Tie::componentTypeID; // = 1
id = BlueHat::componentTypeID; // = 0, gets the same number as struct Hat : Component<Hat>{}
}
有什么好的解决办法吗?我想理想地定义任何新结构而不将参数传递给基本构造函数。我意识到我为此使用了 CRTP,这正是我为使其工作所做的,但必须有更简单的方法,对吗?
编辑:实际上我很惊讶解决方案并不简单,我想要的只是为我在全局命名空间中创建的每个 class 获取一个新 ID,我想要么是编译时间要么运行时间。
我找不到一种简单的方法来扩展您当前的解决方案来执行此操作,除非您想开始在每个继承声明符上抛出 virtual
,并记住每次都这样做.
无论如何,“计数类型”似乎有点反模式。通过 typeid
.
如果你真的需要一个 int
,你可以让一些管理器 class 接受一个 std::type_info
并给你一个对该类型唯一的 int
,可能使用一张为其供电的地图。但是,如果您可以将 std::type_info
存储在第一位,那就更好了。缺点是此信息将无法静态使用(即“在编译时”)。
您不需要继承类型上的(运行时)计数器。
您甚至可以使用模板变量 (C++14):
std::size_t getId()
{
static std::size_t counter = 0;
return counter++;
}
template <typename T>
std::size_t Id = getId();
Demo.