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_ptrstd::weak_ptrstd::reference_wrapper甚至原始指针而不是std::unique_ptr,具体取决于上的情况。但是,如果没有更多上下文,很难判断哪个是正确的,所以我在这个例子中使用了基线 unique_ptr