Passing union enums into functions in c++

Viewed 71

I'm helping out on a project to decompile a video game.

The game has a function to set the active camera:

SetActiveCam(LevelIds level, int16_t cam)

"LevelIds" is just an enum class with int16_t values (a complete set from 0 to 15).

I want to do something similar for cam IDs:

SetActiveCam(LevelIds level, CameraIds cam)

However, cam ID values are context sensitive dependent on the level.

For instance, CamID #2 might be the OptionsMenu in the "Menu" level, but something else entirely in the "Forest" level.

Below I have created a CameraIds union with all "Menu" cams named within an enum:

union CameraIds
{
    enum class Menu : int16_t
    {
        eMainMenu_1 = 1,
        eOptions_2 = 2,
        eGamespeakGamepad_3 = 3,
        eMotions_4 = 4,
        eSound_5 = 5,
        eLoad_6 = 6,
        eMotionsGamespeakGamepad_7 = 7,
        eCopyright_10 = 10,
        eLoading_21 = 21,
        eFmvSelect_30 = 30,
        eLvlSelect_31 = 31,
        eGamespeakKeyboard_33 = 33,
        eMotionsGamespeakKeyboard_37 = 37,
        eController_40 = 40,
        eControllerConfig_41 = 41
    } menu;

    enum class Forest : int16_t
    {
        eForestStart_1 = 1,
        eForestSecretScreen_23 = 23
    } forest;

    int16_t raw;
};

However, the below function call...

SetActiveCam(LevelIds::eMenu_0, CameraIds::Menu::eOptions_2);

Results in the following error message:

No suitable constructor exists to convert from "CameraIds::Menu" to "CameraIds"

Any thoughts?

The idea was to cut down on magic numbers by giving proper names to some of these Camera IDs.

The format "CameraIds::LEVEL::SCREEN" is one that I really like - but I'm having trouble making it work...

Is there something obvious I'm missing? Casting might be it... but is that good practice?

EDIT: Added another enum to mitigate some confusion.

2 Answers

You want to pass only enum, but your argument type is whole union. You need to change second argument type from CameraIDs to CameraIDs::Menu.

I would suggest an alternative design. Since the level is essentially encoded by the type of the camera id, how about a set of overloads like this which use the level id based on the argument:

void SetActiveCam(MenuCameraIds cam) {
    SetActiveCam(LevelIds::eMenu_0, cam);
}
void SetActiveCam(ForestCamera cam) {
    SetActiveCam(LevelIds::eForest_0, cam);
}
Related