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);
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);
}