gpt4 book ai didi

c++ - 使用指针算法遍历同构 POD 结构

转载 作者:搜寻专家 更新时间:2023-10-31 02:06:56 25 4
gpt4 key购买 nike

假设我正在编写一个游戏,设计一种输入重映射机制。它有这两个结构:

struct KeyboardSettings
{
InputSource dashInput;
InputSource jumpInput;
InputSource bombInput;
InputSource switchScreenLeft;
InputSource switchScreenRight;
InputSource pauseInput;

InputSource moveUp;
InputSource moveDown;
InputSource moveLeft;
InputSource moveRight;
};

struct JoystickSettings
{
InputSource dashInput;
InputSource jumpInput;
InputSource bombInput;
InputSource switchScreenLeft;
InputSource switchScreenRight;
InputSource pauseInput;

InputSource movementAxisX;
InputSource movementAxisY;
};

现在,我希望我的系统在重新分配 key 时确实找出重复项,类似于:

void UIInputRemappingButtonGroup::assignRemappingUniquely(InputSource& curSource, InputSource newSource)
{
for (InputSource* orgSource : /* iterate through structure's members */)
if (*orgSource == newSource) *orgSource = curSource;

curSource = newSource;
}

因为我希望这段代码尽可能通用,所以我考虑将这两个结构视为 InputSource 的“数组”,因此 UIInputRemappingButtonGroup 会接收一个 InputSource* 和一个 size_t 代表数组的开始和大小,我会做这样的事情:

void UIInputRemappingButtonGroup::assignRemappingUniquely(InputSource& curSource, InputSource newSource)
{
for (InputSource* orgSource = sourceCollection; orgSource != sourceCollection+sourceCollectionSize; ++orgSource)
if (*orgSource == newSource) *orgSource = curSource;

curSource = newSource;
}

因此,如果我在屏幕上工作以重新映射键盘按钮,我将有一个 KeyboardSettings keyboardSettings,我会将它传递给 UIInputRemappingButtonGroup,如下所示:

buttonGroup.setInputSourceCollection(&keyboardSettings.dashInput, sizeof(keyboardSettings)/sizeof(InputSource));

同样,如果我有一个 JoystickSettings joystickSettings,我可以使用以下代码将它传递给 UIInputRemappingButtonGroup:

buttonGroup.setInputSourceCollection(&joystickSettings.dashInput, sizeof(joystickSettings)/sizeof(InputSource));

问题是,我怀疑这会触发未定义的行为。尽管这两个结构是标准布局和琐碎的(因此也是 POD),但我没有在标准中找到任何支持这种技术有效性的东西,或者至少将它从 UB 领域中移除。安全吗?

InputSource 定义如下:

class InputSource final
{
private:
enum class Type : uint8_t { Keyboard, MouseButton, MouseAxis, JoystickButton, JoystickAxis };

Type type;
size_t attribute;

// Constructor private
InputSource() = default;
InputSource(Type type, uint32_t attr) : type(type), attribute(attr) {}
public:
std::string getInputName(LocalizationManager& lm);

static InputSource keyboardKey(size_t scanCode);

static InputSource mouseButton(sf::Mouse::Button button);
static InputSource mouseX, mouseY;
static InputSource mouseWheel(sf::Mouse::Wheel wheel);

static InputSource joystickButton(unsigned int button);
static InputSource joystickAxis(sf::Joystick::Axis axis);

friend bool operator==(InputSource in1, InputSource in2);
friend bool operator<(InputSource in1, InputSource in2);

friend bool readFromStream(sf::InputStream& stream, InputSource& in);
friend bool writeToStream(OutputStream& stream, const InputSource& in);

friend struct std::hash<InputSource>;
};

如上所示,它满足标准布局要求(所有非静态数据成员具有相同的访问控制,没有虚函数或虚基类,没有引用类型的非静态数据成员,以及所有非静态数据members standard-layout),以及琐碎的需求(琐碎的构造函数、复制运算符和析构函数),所以它也是POD。

那么,从标准的角度来看,我设计的这种机制是否安全?

最佳答案

当您想将结构视为数组时,使用实际数组通常是有意义的。这个数组可以安全地迭代。

struct KeyboardSettings
{
enum input {
dashInput,
jumpInput,
bombInput,
switchScreenLeft,
switchScreenRight,
pauseInput,
moveUp,
moveDown,
moveLeft,
moveRight,

count,
};
InputSource sources[count]; // you can use std::array if you prefer
};

用法:

using i = KeyboardSettings::input;
KeyboardSettings s;
s.sources[i::moveUp];
// instead of
// s.moveUp;

这可以通过重载下标运算符来简化为 s[i::moveUp]


如果您真的想继续使用成员(member),可以使用 Boost Fusion图书馆。

关于c++ - 使用指针算法遍历同构 POD 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49482598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com