C++ 模板方法 return 引用私有映射值,其中值的类型是 T 的父级
C++ Template method return ref to private map value where value's type is parent of T
实际上我遇到了一个问题,对某人来说是一个挑战,你能帮我解决这个问题吗? :
class UItemEntity : public UObject
{
GENERATE_BODY()
public:
template<typename T=FItemComponent>
T& GetComponent()
{
auto Result = Components[TYPE_ID(T)];
T Comp = reinterpret_cast<T>(Result);
return Comp;
}
private:
/** Map from Component's type ID to one of their instance associated to this entity. */
TMap<const char*, FItemComponent> Components;
}
(这是虚幻的 c++ 代码,但仍然是 c++ :P)
用法示例:
struct FTestComponent : public FItemComponent { }
UItemEntity* Item;
FTestComponent& Comp = Item->GetComponent<FTestComponent>();
我不知道如何转换从地图中检索到的值...我尝试了静态、动态和重新解释转换,但 none 成功了。
这是我遇到的错误类型:
ItemEntity.h: [C2440] 'reinterpret_cast': cannot convert from 'ValueType' to 'T'
这可能是一个体系结构问题,但我不知道如何解决:/而且我真的需要这个 ItemEntity 上的 GetComponent。
谢谢!
编辑:
在@Frank 的帮助下,我终于成功了,需要考虑一些虚幻的东西。
这里是:
class UItemEntity : public UObject
{
GENERATE_BODY()
public:
template<typename T=FItemComponent>
T& GetComponent()
{
const bool IsItemComponentType = std::is_base_of_v<FItemComponent, T>;
check(IsItemComponentType);
FItemComponent* ItemComp = *Components.Find(TYPE_ID(T));
return Cast<T>(ItemComp);
}
private:
/** Map from Component's type ID to one of their instance associated to this entity. */
TMap<const char*, FItemComponent*> Components;
}
可能有一些我不知道的特定于虚幻引擎的恶作剧在起作用,但在通用 C++ 代码中,它看起来像这样:
class UItemEntity : public UObject
{
GENERATE_BODY()
public:
template<typename T>
T& GetComponent()
{
static_assert(std::is_base_of_v<FItemComponent, T>);
return *static_cast<T*>(Components.at(TYPE_ID(T)).get());
}
private:
/** Map from Component's type ID to one of their instance associated to this entity. */
TMap<const char*, std::unique_ptr<FItemComponent>> Components;
}
解释:
- 元素存储为指针,因为可以在其中存储不同的类型。
使用 at()
是因为如果缺少该条目,函数将无法 return。
static_cast<>
让编译器知道从 base 到 derived 的转换是有意的。
- 指针被解除引用为
*
的引用。
- 根据评论中的讨论,我用
static_assert()
替换了默认模板参数。
您可能想要使用std::shared_ptr
、std::weak_ptr
、std::reference_wrapper
甚至原始指针而不是std::unique_ptr
,具体取决于上的情况。但是,如果没有更多上下文,很难判断哪个是正确的,所以我在这个例子中使用了基线 unique_ptr
。
实际上我遇到了一个问题,对某人来说是一个挑战,你能帮我解决这个问题吗? :
class UItemEntity : public UObject
{
GENERATE_BODY()
public:
template<typename T=FItemComponent>
T& GetComponent()
{
auto Result = Components[TYPE_ID(T)];
T Comp = reinterpret_cast<T>(Result);
return Comp;
}
private:
/** Map from Component's type ID to one of their instance associated to this entity. */
TMap<const char*, FItemComponent> Components;
}
(这是虚幻的 c++ 代码,但仍然是 c++ :P)
用法示例:
struct FTestComponent : public FItemComponent { }
UItemEntity* Item;
FTestComponent& Comp = Item->GetComponent<FTestComponent>();
我不知道如何转换从地图中检索到的值...我尝试了静态、动态和重新解释转换,但 none 成功了。
这是我遇到的错误类型:
ItemEntity.h: [C2440] 'reinterpret_cast': cannot convert from 'ValueType' to 'T'
这可能是一个体系结构问题,但我不知道如何解决:/而且我真的需要这个 ItemEntity 上的 GetComponent。
谢谢!
编辑:
在@Frank 的帮助下,我终于成功了,需要考虑一些虚幻的东西。
这里是:
class UItemEntity : public UObject
{
GENERATE_BODY()
public:
template<typename T=FItemComponent>
T& GetComponent()
{
const bool IsItemComponentType = std::is_base_of_v<FItemComponent, T>;
check(IsItemComponentType);
FItemComponent* ItemComp = *Components.Find(TYPE_ID(T));
return Cast<T>(ItemComp);
}
private:
/** Map from Component's type ID to one of their instance associated to this entity. */
TMap<const char*, FItemComponent*> Components;
}
可能有一些我不知道的特定于虚幻引擎的恶作剧在起作用,但在通用 C++ 代码中,它看起来像这样:
class UItemEntity : public UObject
{
GENERATE_BODY()
public:
template<typename T>
T& GetComponent()
{
static_assert(std::is_base_of_v<FItemComponent, T>);
return *static_cast<T*>(Components.at(TYPE_ID(T)).get());
}
private:
/** Map from Component's type ID to one of their instance associated to this entity. */
TMap<const char*, std::unique_ptr<FItemComponent>> Components;
}
解释:
- 元素存储为指针,因为可以在其中存储不同的类型。 使用
at()
是因为如果缺少该条目,函数将无法 return。static_cast<>
让编译器知道从 base 到 derived 的转换是有意的。- 指针被解除引用为
*
的引用。 - 根据评论中的讨论,我用
static_assert()
替换了默认模板参数。
您可能想要使用std::shared_ptr
、std::weak_ptr
、std::reference_wrapper
甚至原始指针而不是std::unique_ptr
,具体取决于上的情况。但是,如果没有更多上下文,很难判断哪个是正确的,所以我在这个例子中使用了基线 unique_ptr
。