Home > Blockchain >  An issue on switch/case statements with a class implementing enums (to be derived)
An issue on switch/case statements with a class implementing enums (to be derived)

Time:07-10

after some searching on the Net, I found a satisfying, at least for me, solution for C 14 enums inheritance, as you can see in the code below, where only base class is mentioned. Everything works fine except for switch/case usage where a compilation error occurs.

May someone suggest a simple modification to MyEnum class in order to be used in switch/case statements, too?

Many thanks.

#include <iostream>
#include <cstdint>

class MyEnum
{
    public:

        static const MyEnum VAL_1;
        static const MyEnum VAL_2;
        static const MyEnum VAL_3;

        MyEnum() {}

        explicit MyEnum(uint8_t val) : value(val) {}

        virtual ~MyEnum() {}

        bool operator<(const MyEnum& other) const { return value < other.value; }
        bool operator==(const MyEnum& other) const { return value == other.value; }
        bool operator!=(const MyEnum& other) const { return !(operator==(other)); }

        operator uint8_t() const { return value; }

    protected:

        static const uint8_t Val1 = 1;
        static const uint8_t Val2 = 2;
        static const uint8_t Val3 = 3;

        uint8_t value;
};

const MyEnum MyEnum::VAL_1(Val1);
const MyEnum MyEnum::VAL_2(Val2);
const MyEnum MyEnum::VAL_3(Val3);

int main()
{
    MyEnum e;

    e = MyEnum::VAL_1;

    if (e == MyEnum::VAL_1)
        std::cout << "Compiles" << std::endl;

    switch (e)
    {
        case MyEnum::VAL_1:
        {
            std::cout << "Doesn't compile" << std::endl;
        }
    }

    exit(0);
}

Thanks for all your answers, as I stated in my first post, my issue is mainly on C enums inheritance, then please find below an updated example.

Currently I have 2 issues:

  • The first MyEnum class implementation stops working enabling toString() methods, just compile with -DTO_STRING and you can see the effect on e value. I understand i'm trying to do something ugly, is there a correct way to achieve the same result?

  • I have a bunch of code using functions that take MyEnum type as input and I cannot modify it. Using the second suggested MyEnum implementation that wraps real enum, just compile with -DMYENUM_2, I get an error because wrapped enum type (vale) is expected as function input, not MyEnum itself. Any ideas?

Thanks again.

#include <iostream>
#include <cstdint>

#ifndef MYENUM_2

class MyEnum
{
    public:

        static const MyEnum VAL_1;
        static const MyEnum VAL_2;
        static const MyEnum VAL_3;

        MyEnum() {}

        constexpr explicit MyEnum(uint8_t val) : value(val) {}

        bool operator<(const MyEnum& other) const { return value < other.value; }
        bool operator==(const MyEnum& other) const { return value == other.value; }
        bool operator!=(const MyEnum& other) const { return !(operator==(other)); }

        constexpr operator uint8_t() const { return value; }

#ifdef TO_STRING
        virtual std::string toString()
        {
            printf("value = %d\n", value);

            if (value == Val1)
                return "1";
            else if (value == Val2)
                return "2";
            else if (value == Val3)
                return "3";
        }
#endif

    protected:

        static const uint8_t Val1 = 1;
        static const uint8_t Val2 = 2;
        static const uint8_t Val3 = 3;

        uint8_t value;
};

constexpr MyEnum MyEnum::VAL_1(Val1);
constexpr MyEnum MyEnum::VAL_2(Val2);
constexpr MyEnum MyEnum::VAL_3(Val3);

class MyDerivedEnum : public MyEnum
{
    public:

        static const MyDerivedEnum VAL_4;
        static const MyDerivedEnum VAL_5;
        static const MyDerivedEnum VAL_6;

        MyDerivedEnum() {}

        constexpr explicit MyDerivedEnum(uint8_t val) : MyEnum(val) {}

#ifdef TO_STRING
        std::string toString()
        {
            printf("value = %d\n", value);

            if (value == Val4)
                return "4";
            else if (value == Val5)
                return "5";
            else if (value == Val6)
                return "6";
        }
#endif

    private:

        static const uint8_t Val4 = 4;
        static const uint8_t Val5 = 5;
        static const uint8_t Val6 = 6;
};

constexpr MyDerivedEnum MyDerivedEnum::VAL_4(Val4);
constexpr MyDerivedEnum MyDerivedEnum::VAL_5(Val5);
constexpr MyDerivedEnum MyDerivedEnum::VAL_6(Val6);

#else

class MyEnum
{
    public:

        typedef enum
        {
            VAL_1 = 1,
            VAL_2,
            VAL_3
        } vale;

        MyEnum() {}
        explicit MyEnum(uint8_t val) : value((vale)val) {}
        virtual ~MyEnum() {}

        bool operator<(const MyEnum& other) const { return value < other.value; }
        bool operator==(const MyEnum& other) const { return value == other.value; }
        bool operator!=(const MyEnum& other) const { return !(operator==(other)); }
        //replaced by operator vale :
        //operator uint8_t() const { return value; }

        MyEnum& operator = (const vale& v)
        {
            value = v;
            return *this;
        }

        operator vale () const
        {
            return value;
        }

        //op ==, !=... to be written

        protected:

            vale value;
};

#endif

class A
{
    public:

        A() {}

        ~A() {}

        void set(MyEnum e)
        {
            printf("e = %d\n", e);
        }
};

#ifndef MYENUM_2

class B : A
{
    public:

        B() {}

        ~B() {}

        void test(MyDerivedEnum e)
        {
            set(e);
        }
};

#endif

int main()
{
    A a;
#ifndef MYENUM_2
    B b;
#endif

    a.set(MyEnum::VAL_1);
#ifndef MYENUM_2
    b.test(MyDerivedEnum::VAL_4);
#endif

    exit(0);
}

CodePudding user response:

Slight modifications to compiles:

class MyEnum
{
    public:

        static const MyEnum VAL_1;
        static const MyEnum VAL_2;
        static const MyEnum VAL_3;

        MyEnum() {}

        constexpr explicit MyEnum(uint8_t val) : value(val) {}

        bool operator<(const MyEnum& other) const { return value < other.value; }
        bool operator==(const MyEnum& other) const { return value == other.value; }
        bool operator!=(const MyEnum& other) const { return !(operator==(other)); }

        constexpr operator uint8_t() const { return value; }

    protected:

        static const uint8_t Val1 = 1;
        static const uint8_t Val2 = 2;
        static const uint8_t Val3 = 3;

        uint8_t value;
};

constexpr MyEnum MyEnum::VAL_1(Val1);
constexpr MyEnum MyEnum::VAL_2(Val2);
constexpr MyEnum MyEnum::VAL_3(Val3);

Demo

CodePudding user response:

What about using Pete Becker' solution ? Add an enumerated type -and associated conversion operators- ? You can do it this way

#include <iostream>
#include <cstdint>

class MyEnum
{
public:
  typedef enum {
    VAL_1 = 1,
    VAL_2,
    VAL_3
  } vale;
  MyEnum() {}
  explicit MyEnum(uint8_t val) : value((vale)val) {}
  virtual ~MyEnum() {}
  bool operator<(const MyEnum& other) const { return value < other.value; }
  bool operator==(const MyEnum& other) const { return value == other.value; }
  bool operator!=(const MyEnum& other) const { return !(operator==(other)); }
 //replaced by operator vale :
 //operator uint8_t() const { return value; }
 MyEnum& operator = (const vale& v) {
   value = v;
   return *this;
 }
 operator vale () const {
   return value;
 }
 //op ==, !=... to be written
protected:
  vale value;
};

int main() {
  MyEnum e;
  e = MyEnum::VAL_1;
  if (e == MyEnum::VAL_1)
    std::cout << "Compiles" << std::endl;
  switch (e) {
  case MyEnum::VAL_1:
     std::cout << "compiles now" << std::endl;
     break;
  }
  exit(0);
}
  • Related