C++ 结合枚举映射

C++ combine maps of enums

假设我有一些 class 游戏层次结构。像这样: PhysicalObjectBaseUnit 的父级 BaseArcher 等等... 每个层级都会添加自己的统计信息。

任何物理对象 - 都有速度和大小。 任何 BaseUnit - 生命值。

我希望它被用作枚举,所以:

enum class PhysicalObjectStats { speed, size };
enum class BaseUnitStats { hitpoints };

当然,BaseArcher 必须包括 PhysicalObject 和 BaseUnit 的统计信息。 如何制作这样的架构? 我试图以如此简单的方式实现它,仅使用映射和动态多态性,但它无法编译(老实说,这是有充分理由的):

https://coliru.stacked-crooked.com/a/8496247abd3e6f41

此外,我尝试创建一个特定的 StatsHolder class 并且它有效,但在所有可能的用例(设置和获取值)中看起来都很糟糕。实际上,如果不向下转换,我无法在 class 之外获得价值:

https://coliru.stacked-crooked.com/a/46f4f4aec6a22c57

另外,我的stats可能不仅仅是int,还有bool等一些类型。我尝试为它们使用 std::variant 并且它工作正常,但我不想考虑它,使用“GetStats()”方法。所以,理想情况下我想要这样的界面:

std::shared_ptr<PhysicalObject> unit = std::make_shared<BaseUnit>();
unit->SetValue<int>(PhysicalObjectStats::speed);
std::cout << unit->GetValue<bool>(BaseUnitStats::HasArmor);

这使任务变得更加困难。关于如何以好的方式完成它有什么建议吗?

我看不出 map 和 enum 的意义,而普通会员似乎可以做到:

struct PhysicalObject
{
    int speed = 0;
    int size = 0;
};
struct BaseUnitStats : PhysicalObject
{
// or composition:
// physicalObject PhysicalObject;
    int hitpoints = 0;
};

为了你的 StatsHolder class:

template<class StatsEnum>
struct StatsHolder
{
    void SetStats(StatsEnum stat, int value) { stats[stat] = value; }
    int GetStats(StatsEnum stat) const { return stats.at(stat); }
private:
    std::map<StatsEnum, int> stats;
};

派生 classes 必须使用 using:

struct BaseUnit : PhysicalObject, StatsHolder<BaseUnitStats> {
    using PhysicalObject::GetStats;
    using StatsHolder<BaseUnitStats>::GetStats;
    using PhysicalObject::SetStats;
    using StatsHolder<BaseUnitStats>::SetStats;

    BaseUnit() { SetStats(BaseUnitStats::hitpoints, 300); }
};

Demo