我定义了
struct
和 enum
,如下所示:
enum class ETerrainType : uint16_t {/*Enum types here*/};
enum class EBuildingType : uint16_t {/*Enum types here*/};
enum class EDecorationType : uint16_t {/*Enum types here*/};
struct Tile
{
ETerrainType TerrainType;
EBuildingType BuildingType;
EDecorationType DecorationType;
};
请注意,结构体的成员变量都继承相同的类型(
uint16_t
)。
我有一容器瓷砖
std::vector<Tile> Tiles;
void TerrainTypeFunc()
{
for (Tile& tile : Tiles)
{
DoSomething(static_cast<uint16_t>(tile.TerrainType));
}
}
void BuildingTypeFunc()
{
for (Tile& tile : Tiles)
{
DoSomething(static_cast<uint16_t>(tile.BuildingType));
}
}
void DecorationTypeFunc()
{
for (Tile& tile : Tiles)
{
DoSomething(static_cast<uint16_t>(tile.DecorationType));
}
}
在我看来,当每个函数之间唯一的区别是访问的成员时,重新定义每个函数是一种糟糕的做法。
我的第一个想法是将成员变量存储为
uint16_t
的固定数组; 但是,我想利用结构打包(例如编译器可以将这三个成员变量存储在一个 64 位字中)。另一种选择是使用偏移量来访问变量;例如,获取指向
TerrainType
的指针,并将该指针加 1 以获得 BuildingType
,或者向该指针加 2 以获得 DecorationType
。第三个选项是使用一个函数,该函数通过分支确定在运行时使用哪个参数。我不想这样做,因为我不想承担任何运行时成本。
我的问题:
如何使用更少的代码定义这三个函数,而不产生额外的运行时成本?
我认为最好使用模板来完成,如果不能则使用宏,但我不知道如何完成。
您可以使用
std::invoke
函数将每个数据成员视为传递给公共函数的可调用对象,如下所示:
template<typename F>
void DoSomethingOn(F typeLookup)
{
for (Tile& tile : Tiles)
{
DoSomething(static_cast<uint16_t>(std::invoke(typeLookup ,tile )));
}
}
你可以这样称呼它:
doSomethingOn(&Tile::TerrainType);
doSomethingOn(&Tile::BuildingType);
doSomethingOn(&Tile::DecorationType);