编写仅结构/类成员变量名称不同的类似函数的更好方法?

问题描述 投票:0回答:1

我定义了

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

据我所知,这是不好的做法,因为很难确定要使用什么偏移量,因为在不同情况下可能有也可能没有结构打包。另外,我认为这不利于可读性。

第三个选项是使用一个函数,该函数通过分支确定在运行时使用哪个参数。我不想这样做,因为我不想承担任何运行时成本。

我的问题:
如何使用更少的代码定义这三个函数,而不产生额外的运行时成本?
我认为最好使用模板来完成,如果不能则使用宏,但我不知道如何完成。

c++ templates vector macros packing
1个回答
0
投票

您可以使用

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);
© www.soinside.com 2019 - 2024. All rights reserved.