Home > Software engineering >  Is there a stratified enum, or base class for enum in C ?
Is there a stratified enum, or base class for enum in C ?

Time:06-30

I encountered a situation where I need to write many enums, but wish to separate, or stratify all the enums into groups of enums of smaller length, as the following shows:

enum class health {HP,Shield};
enum class battle {STR,AGL,INT};

// such struct DOESN'T WORK, either with instantiated object or direct struct referencing
struct hero_num{
    enum class health {HP,Shield};
    enum class battle {STR,AGL,INT};
};

The reason I am writing a struct to hold all enums is that I want to use all those enums by only referencing the hero_num type, so as to utilize functions as such:

// A class definition scope
{
...
    int get_stats(hero_num stats_type);
    void add_stats(hero_num stats_type, int value);
...
};

// I wish to call all the enum with ONE definition
void add_stats(health::HP,100);
void add_stats(battle::STR,10);

I am not sure whether aggregating declared enum into struct, or create a base class enum for all enum would work as intended. How should I design my structure to make such a function call? Or, in general, how could I break a lengthy enum into smaller enums, and make the right type reference?

CodePudding user response:

You may want to ask yourself if you need enums, particularly, or if you actually just want some kind of tag. Enums allow runtime switching based on an object of the enum type, whereas for the use case you've shown (health::HP, battle::STR) the property type is known at compile time, and a type-based tag approach may suffice.

#include <type_traits>

struct health {
    struct HP{};
    struct Shield{};
};

struct battle {
    struct STR{};
    struct AGL{};
    struct INT{};
};

struct hero_num : health, battle {};
// hero_num::HP
// hero_num::Shield
// hero_num::STR
// hero_num::AGL
// hero_num::INT

struct hero {
    template<typename property>
    void add_stats(int value) {
        if constexpr (std::is_same_v<property, hero_num::HP>) {
            hp  = value;
        }
        else if constexpr (std::is_same_v<property, hero_num::Shield>) {
            shield  = value;
        }
        // ... and so on
    }

  private:
    int hp{};
    int shield{};
    int strenght{};
    int agility{};
    int intelligence{};
};

int main() {
    hero my_hero{};
    my_hero.add_stats<hero_num::HP>(12);
}

CodePudding user response:

There must be a better hack but i would use the enum underlying type as a base type for function calls like this :

enum health {
    HP = 0,
    Shield = 1
};
enum battle {
    STR = Shield   1,
    AGL,
    INT
};

void add_stats(int stats_type, int value); // underlying type is int
int get_stats(int stats_type);   

and then call it as you wanted :

    add_stats(health::HP, 100);
    add_stats(battle::STR, 10);

I use enum in this example because i found it easier to write here. You can actually do the same with C 11 and enum class, but you'll need to static_cast to the enum underlying type.

  • Related