将类型映射到整数值后,如何在给定整数值的情况下取回类型?
Posted
技术标签:
【中文标题】将类型映射到整数值后,如何在给定整数值的情况下取回类型?【英文标题】:After mapping a type to an integral value, how do I get the type back given an integral value? 【发布时间】:2019-12-06 14:03:47 【问题描述】:我正在尝试构建这个实体组件系统,我有这个模板化的容器类,用于存储所有组件类型,并且对于每个传递的类型,下面的代码负责将类型映射到索引,以便我可以将它用作 std::map 的键(其中值是指向“向量”的指针)。因此,例如调用 typeId<RectComponent>()
可能会返回值 2,假设 typeId 类之前使用其他模板参数实例化了 2 次:
#pragma once
using uInt = size_t;
class typeIdBase
private:
static uInt internal_generateTypeID()
static uInt typeIDCounter;
return typeIDCounter++;
template<typename T> friend class typeId;
;
template<typename T>
class typeId
public:
operator uInt() const return id;
private:
static inline uInt id = typeIdBase::internal_generateTypeID();
;
问题是现在我还需要走相反的方向,我需要一个返回给定 size_t 值的类型,所以例如在我的代码中typename idType<2>::type
应该相当于键入RectComponent
。
按照上面与值 2 关联的 RectComponent 的示例,typeId<typename idType<2>::type>()
也应该返回 2
,只是为了清楚起见。
我被卡住了,不知道如何到达那里,有什么建议吗?
【问题讨论】:
我认为不是这个把戏。您需要在某处写出所有类型和数字。或者制作一个脚本来生成它们。 【参考方案1】:就在你这样做的时候
typeId<typename idType<2>::type>()
您要求编译器使用在编译时未知的模板参数值来实例化模板。而这在 C++ 中是行不通的。模板只是编译器的代码蓝图,对于它们实例化的每组不同的参数,都有一个模板化代码版本,其中包含在翻译单元中实际编译的具体类型。在运行时,这些模板都不存在,您只有不同的实例化版本,仅此而已。
所以这种类型的实现是行不通的。根据您的实际问题,您必须在编译时提供这样的映射,或者找到替代解决方案。
【讨论】:
【参考方案2】:您应该非常小心使用示例中的静态初始化程序,因为给定类型的 id 可能会在编译期间发生变化。
不幸的是,没有办法将索引映射回类型 - 正如@user253751 已经评论的那样。
因为您说要使用索引作为地图的键,所以我建议改用type_index
。
这允许您将类型直接用作地图的键。 如果您想为给定类型存储一组小部件,您可以使用以下内容:
Live Demo for Testing
#include <iostream>
#include <memory>
#include <typeindex>
#include <vector>
#include <map>
#include <string>
class WidgetMap
public:
template<typename T>
void addWidget(const T& val)
auto idx = std::type_index(typeid(T));
if(m_map.find(idx) == m_map.end())
m_map[idx] = std::make_shared<std::vector<T>>();
auto vecPtr = std::static_pointer_cast<std::vector<T>>(m_map[idx]);
vecPtr->push_back(val);
template<typename T>
std::shared_ptr<std::vector<T>> getWidgets()
auto idx = std::type_index(typeid(T));
auto it = m_map.find(idx);
if(it == m_map.end())
throw std::runtime_error(std::string"No widget stored for type " + typeid(T).name());
return std::static_pointer_cast<std::vector<T>>(it->second);
private:
std::map<std::type_index, std::shared_ptr<void>> m_map;
;
然后您可以使用您的小部件类型作为键:
struct ExampleWidget
std::string message;
;
// Usage:
WidgetMap m;
// Add widgets
m.addWidget(ExampleWidget"Hello");
m.addWidget(ExampleWidget"World");
// retrieve widgets by type
auto exampleWidgets = m.getWidgets<ExampleWidget>();
for(auto& val : *exampleWidgets)
std::cout << val.message << std::endl;
【讨论】:
我的代码已经可以做到这一点,我可以做到getVector<RectComponent>()
并得到一个向量,在这个相应的例子中我需要的是一个std::type_index
它应该给我一个相应的类型。因为如果您想象一个带有std::map<std::type_index, size_t> componentsId
的实体,它只存储组件的 id,当然我希望能够在需要时访问特定的组件,但是在销毁时我想要一个循环范围,该映射可以将 type_index 转换为正确的类型,以便访问正确的向量并删除组件。以上是关于将类型映射到整数值后,如何在给定整数值的情况下取回类型?的主要内容,如果未能解决你的问题,请参考以下文章