Base enum class inheritance

C++Enums

C++ Problem Overview


Is there a pattern where I can inherit enum from another enum in C++??

Something like that:

enum eBase 
{
   one=1, two, three
};


enum eDerived: public eBase
{
   four=4, five, six
};

C++ Solutions


Solution 1 - C++

#include <iostream>
#include <ostream>

class Enum
{
public:
    enum
    {
        One = 1,
        Two,
        Last
    };
};

class EnumDeriv : public Enum
{
public:
    enum
    {
        Three = Enum::Last,
        Four,
        Five
    };
};

int main()
{
    std::cout << EnumDeriv::One << std::endl;
    std::cout << EnumDeriv::Four << std::endl;
    return 0;
}

Solution 2 - C++

Not possible. There is no inheritance with enums.

You can instead use classes with named const ints.

Example:

class Colors
{
public:
  static const int RED = 1;
  static const int GREEN = 2;
};

class RGB : public Colors
{
  static const int BLUE = 10;
};


class FourColors : public Colors
{
public:
  static const int ORANGE = 100;
  static const int PURPLE = 101;
};

Solution 3 - C++

You can't do that directly, but you could try to use solution from this article.

The main idea is to use the helper template class which holds enum values and has the type cast operator. Considering that the underlying type for enum is int you can use this holder class seamlessly in your code instead of the enum.

Solution 4 - C++

Unfortunately it is not possible in C++14. I hope we will have such a language feature in C++17. As you already got few workarounds for your problem I won't provide a solution.

I would like to point out that the wording should be "extension" not "inheritance". The extension allows for more values (as you're jumping from 3 to 6 values in your example) whereas inheritance means putting more constraints to a given base class so the set of possibilities shrinks. Therefore, potential casting would work exactly opposite from inheritance. You can cast derived class to the base class and not vice-verse with class inheritance. But when having extensions you "should" be able to cast the base class to its extension and not vice-verse. I am saying "should" because, as I said such a language feature still doesn't exist.

Solution 5 - C++

How about this? Ok an instance is created for every possible value, but besides that its very flexible. Are there any downsides?

.h:

class BaseEnum
{
public:
  static const BaseEnum ONE;
  static const BaseEnum TWO;

  bool operator==(const BaseEnum& other);

protected:
  BaseEnum() : i(maxI++) {}
  const int i;
  static int maxI;
};

class DerivedEnum : public BaseEnum
{
public:
  static const DerivedEnum THREE;
};

.cpp:

int BaseEnum::maxI = 0;

bool BaseEnum::operator==(const BaseEnum& other) {
  return i == other.i;
}

const BaseEnum BaseEnum::ONE;
const BaseEnum BaseEnum::TWO;
const DerivedEnum DerivedEnum::THREE;

Usage:

BaseEnum e = DerivedEnum::THREE;
    
if (e == DerivedEnum::THREE) {
    std::cerr << "equal" << std::endl;
}

Solution 6 - C++

Well, if you'll define enum with the same name in derived class and start it from last item of correspondent enum in base class, you'll receive almost what you want - inherited enum. Look at this code:

class Base
{
public:
    enum ErrorType
    {
        GeneralError,
        NoMemory,
        FileNotFound,
        LastItem,
    };
};

class Inherited: public Base
{
public:
    enum ErrorType
    {
        SocketError = Base::LastItem,
        NotEnoughBandwidth,
    };
};

Solution 7 - C++

As stated by bayda, enum's don't (and/or shouldn't) have functionality, so I've taken the following approach to your quandary by adapting Mykola Golubyev's response:

typedef struct
{
    enum
    {
        ONE = 1,
        TWO,
        LAST
    };
}BaseEnum;

typedef struct : public BaseEnum
{
    enum
    {
        THREE = BaseEnum::LAST,
        FOUR,
        FIVE
    };
}DerivedEnum;

Solution 8 - C++

You can use a project SuperEnum to create extendable enumerations.

/*** my_enum.h ***/
class MyEnum: public SuperEnum<MyEnum>
{
public:
    MyEnum() {}
    explicit MyEnum(const int &value): SuperEnum(value) {}

    static const MyEnum element1;
    static const MyEnum element2;
    static const MyEnum element3;
};

/*** my_enum.cpp ***/
const MyEnum MyEnum::element1(1);
const MyEnum MyEnum::element2;
const MyEnum MyEnum::element3;

/*** my_enum2.h ***/
class MyEnum2: public MyEnum
{
public:
    MyEnum2() {}
    explicit MyEnum2(const int &value): MyEnum(value) {}

    static const MyEnum2 element4;
    static const MyEnum2 element5;
};

/*** my_enum2.cpp ***/
const MyEnum2 MyEnum2::element4;
const MyEnum2 MyEnum2::element5;

/*** main.cpp ***/
std::cout << MyEnum2::element3;
// Output: 3

Solution 9 - C++

Kind of hacky but this is what I came up with if dealing with scoped enums:

enum class OriginalType {
   FOO,  // 0
   BAR   // 1
   END   // 2
};

enum class ExtendOriginalType : std::underlying_type_t<OriginalType> {
   EXTENDED_FOO = static_cast<std::underlying_type_t<OriginalType>>
                                           (OriginalType::END), // 2
   EXTENDED_BAR  // 3
};

and then use like:

OriginalType myOriginalType = (OriginalType)ExtendOriginalType::EXTENDED_BAR;

Solution 10 - C++

This answer is a variant of Brian R. Bondy answer. Since has been requested in a comment I'm adding it as answer. I'm not pointing about if it really worths though.

#include <iostream>

class Colors
{
public:
    static Colors RED;
    static Colors GREEN;
  
    operator int(){ return value; }
    operator int() const{ return value; }
  
protected:
    Colors(int v) : value{v}{} 
  
private:
    int value;
};

Colors Colors::RED{1};
Colors Colors::GREEN{2};

class RGB : public Colors
{
public:
    static RGB BLUE;
    
private:
    RGB(int v) : Colors(v){}
};

RGB RGB::BLUE{10};
    
int main ()
{
  std::cout << Colors::RED << " " << RGB::RED << std::endl;
}

Live at Coliru

Solution 11 - C++

Impossible.
But you can define the enum anonymously in a class, then add additional enum constants in derived classes.

Solution 12 - C++

enum xx {
   ONE = 1,
   TWO,
   xx_Done
};

enum yy {
   THREE = xx_Done,
   FOUR,
};

typedef int myenum;

static map<myenum,string>& mymap() {
   static map<myenum,string> statmap;
   statmap[ONE] = "One";
   statmap[TWO] = "Two";
   statmap[THREE] = "Three";
   statmap[FOUR] = "Four";
   return statmap;
}

Usage:

std::string s1 = mymap()[ONE];
std::string s4 = mymap()[FOUR];

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSashaView Question on Stackoverflow
Solution 1 - C++Mykola GolubyevView Answer on Stackoverflow
Solution 2 - C++Brian R. BondyView Answer on Stackoverflow
Solution 3 - C++Kirill V. LyadvinskyView Answer on Stackoverflow
Solution 4 - C++Огњен ШобајићView Answer on Stackoverflow
Solution 5 - C++D-rkView Answer on Stackoverflow
Solution 6 - C++HaspemulatorView Answer on Stackoverflow
Solution 7 - C++vigilanceView Answer on Stackoverflow
Solution 8 - C++Dmitry BravikovView Answer on Stackoverflow
Solution 9 - C++jsadlerView Answer on Stackoverflow
Solution 10 - C++MoiaView Answer on Stackoverflow
Solution 11 - C++baydaView Answer on Stackoverflow
Solution 12 - C++Michal CohenView Answer on Stackoverflow