Pulling C++ Enum Class Members Into the Global Namespace - c++

Is there a using directive that imports the members of an enum class directly into the global namespace of a compilation unit?
We have:
enum Lexeme {....lots of names...};
bool Matches(int lookAhead, Lexeme lxm);
This is risky because users frequently forget that the first argument of Matches means "matches either" and write:
if (Matches(ADD,SUB)) ...
The C++ compiler is perfectly happy taking ADD as an int.
So I tried making Lexeme an enum class:
enum class Lexeme { ...}
This catches the error. But now my problem is that all the code that uses Lexeme constants must write the enum class name:
if (Matches(Lexeme::ADD,Lexeme::SUB)) ...
Is there a using directive, or another trick, to pull all of the Lexeme::* names into the current scope? Note, most tokens are used in a class (I get that properly qualifying the constants is one of the safety mechanisms of enum class).
Perhaps a better plan is to change Matches to MatchesAt, or something, to avoid the problem? But I wanted to know the rules for C++ and C++XX, at least.
What I tried:
This is related, but doesn't address the required enum class prefixes.
I also tried something like using foo::bar::Lexeme; but alas to no avail.

You can make an integer wrapper class not convertible to anything else and make some constants out of it.
struct Lexeme
{
private: int m_value;
public: explicit constexpr Lexeme(int value) noexcept
: m_value{value}
{}
};
inline constexpr Lexeme const ADD{1};
inline constexpr Lexeme const SUB{2};
It would probably be a good idea to overload some operators for this class, at least equality and less than.

On a different note, a way to avoid writing Lexeme:: every time would be just to create a shorter alias:
enum class Lexeme { /* lotsa names */ };
using L = Lexeme;
if (Matches(3, L::SUB)) //...
This works well if there is only one or two files where these values are used extensively, and other uses are sparse. I have just had to use a similar solution where I had a Parameter class that read things from XML. I have a enum class ElementType { INTEGER, BOOLEAN, /* etc*/ } and a parsing infrastructure. Within the parser file, I have:
using ET = ElementType;
template<ET et>
struct parser;
// Specializations for each ElementType
template<>
struct parser<ET::INTEGER> {
using type = int;
int parseSingle(const string& s) // ...
}
While outside this file I just have a few usages of ElementType::* constants and I use the full name of the enum class. Should this become too much of a burden, nothing prevents me from ading that alias to a different file.

Related

Make a "typedef" be final (or simulate it)

Is it possible to mark an alias of a type as final (i.e. can't be re-defined in derived class)?
#include <iostream>
class B{
public: using type=std::string;
};
class D : public B{
public: using type=int; //<--- [1] I want a compile error here.
};
int main(){
typename D::type str="abc"; //<--- [2] This line is actually correct.
}
According to http://en.cppreference.com/w/cpp/language/final, it is for function only.
Is there a workaround?
It would be useful as a coder fool-proof in some cases.
No, you cannot.
Trait based types could do it, but the machinery is ugly.
Define a distributed type map maybe via an adl based tag function map.
template<class T>struct tag_t{constexpr tag_t(){} using type=T;};
template<class T>constexpr tag_t<T> tag{};
namespace trait {
template<class T>
constexpr void type_tag( tag_t<T> ){}
template<class T>
using type=typename decltype( type_tag( tag<T> ) )::type;
}
// non-final alias
struct A{
friend constexpr tag_t<int> type_tag(tag_t<A>){return {};}
};
// non-final alias
struct A{
friend constexpr tag_t<char> type_tag(tag_t<A>){return {};}
};
// final alias
struct B{
template<class T, std::enable_if_t< std::is_base_of<B,T>{}, bool> =true>
friend constexpr tag_t<std::string> type_tag(tag_t<T>){return {};}
};
now overriding A's type_tag works with trait::type<> but if you try the same with B you'll get a long incomprehensible error.
This is a bad plan.
Metaclasses will probably let you do something like this as well.
In general, both of these require writing a new sublanguage of C++ to enforce a constraint C++ does not enforce. Possible, but ill-advised unless you have an extemely good reason.
Tangential answer on how we could use enums or other dummies to usefully hide a type.
/*
* Imagine everybody uses managed strings in our project throughout,
* so everyone expects to be able to declare and print strings everywhere,
* especially for debugging...
*/
typedef OurInternalMangedStrings string;
/***/
void InternalStringManager::ReallyDoingNastyInternalStuff()
{
// Within this code casually using managed strings
// to format error messages, etc,
// would be fatal as it will cause nasty recursion.
enum DoNotUseStrings_DeadlockDanger { string, OurInternalMangedStrings };
printError(string ("I had an error here and I don't know why - code ") << errCode);
}
This will produce an error which will hopefully mention both string and DoNotUseStrings_DeadlockDanger, giving the clue.
But it is of limited use for types as while it stops the author from using the word "string", it doesn't stop the code from automatically performing conversion, or using objects of that type that already exist, eg the following will pass without comment if the constructor is not explicit:
printError("I had an error here and I don't know why at all!");
For data values I find it is more useful:
void MyManager::Setup()
{
{ SomeFeature newPimple = new Somefeature;
enum DoNotUseMember {someFeature};
/** set up newPimple using other member data and parameters
when it is ready I will assign it to the member variable "someFeature"
**/
/** any accidental use of a someFeature member will produce error message **/
// Ready to install the new pimpl as the visible feature
MUTEX_RAII(access_feature); // ... Or whatever might be needed
/* can still access someFeature by being explicit */
delete this->someFeature;
this->someFeature = newPimpl;
}
/** other setup code that uses the new feature **/
}
Personally, I would call the new instance someFeature and get the hiding behaviour for free, but many find the name reuse hard to read.
Another way I use this technique is in refactoring. I have a method that happily uses member values to control its behaviour, and then an enhancement is needed where one of the control values must be controlled externally. To implement this, the original no-argument method becomes a shim, calling a new method with the member as the argument.
But how to ensure the new method doesn't accidentally use the member instead of the argument? Personally, I'd make the argument mask the member, but we are again limited by the comprehension of others.

Is is possible to make scoped enum identifiers driectly accessible in C++? [duplicate]

I am using a scoped enum to enumerate states in some state machine that I'm implementing. For example, let's say something like:
enum class CatState
{
sleeping,
napping,
resting
};
In my cpp file where I define a state transition table, I would like to use something equivalent to using namespace X so that I don't need to prefix all my state names with CatState::. In other words, I'd like to use sleeping instead of CatState::sleeping. My transition table has quite a few columns, so avoiding the CatState:: prefix would keep things more compact and readable.
So, is there a way to avoid having to type CatState:: all the time?
Yeah, yeah, I'm already aware of the pitfalls of using namespace. If there's an equivalent for strongly-typed enums, I promise to only use it inside a limited scope in my cpp implementation file, and not for evil.
So, is there a way to avoid having to type CatState:: all the time?
Not before C++20. Just as there's no equivalent for having to type ClassName:: for static class members. You can't say using typename ClassName and then get at the internals. The same goes for strongly typed enums.
C++20 adds the using enum X syntax, which does what it looks like.
You can of course not use enum class syntax, just using regular enums. But then you lose strong typing.
It should be noted that one of the reasons for using ALL_CAPS for weakly typed enums was to avoid name conflicts. Once we have full scoping and strong typing, the name of an enum is uniquely identified and cannot conflict with other names. Being able to bring those names into namespace scope would reintroduce this problem. So you would likely want to use ALL_CAPS again to help disambiguate the names.
So the short answer is no, but fortunately this is going to change in a recently finalized feature set of C++20. According to this accepted proposal you will be able to do the following:
enum class CatState
{
sleeping,
napping,
resting
};
std::string getPurr(CatState state)
{
switch (state)
{
using enum CatState;
// our states are accessible without the scope operator from now on
case sleeping: return {}; // instead of "case CatState::sleeping:"
case napping: return "purr";
case resting: return "purrrrrr";
}
}
You might consider using a typedef to shorten the qualified names:
typedef CatState C;
Or, if the columns are repetitive in a way that they can be generated easily, you might consider using a macro to generate each row in the table, which can lead to very concise (and easier to read) code.
Nicol's answer is correct: the language is designed to make you always qualify scoped enumerators (except in the enum { } scope itself).
However, here is a technique I came up with for "scoped" enumerators that are unscoped within chosen classes. Technically, the enumerators are unscoped, so they will still convert implicitly to int. (Not "strongly-typed" as you put it.) Nevertheless, in the idiom they are accessed using the scope operator after a true enum name, so syntactically there isn't a difference — and therefore it requires C++11.
#define IMPORTABLE_ENUM( TYPENAME, ... ) \
\
struct import_ ## TYPENAME { \
enum TYPENAME { \
__VA_ARGS__ \
}; \
}; \
\
typedef import_ ## TYPENAME :: TYPENAME TYPENAME;
// usage:
IMPORTABLE_ENUM ( duck, huey, dewey, louie )
duck d = duck::dewey; // can't use unscoped enumerators here
struct duck_madness : private import_duck { // but inside a derived class
duck who_did_it() { return huey; } // qualification is unnecessary
};
I would also love to have this possibility and I find the limitation quite annoying. It's usually best to have the programmer decide which features he wants to use. Either explicit scoping or the more convenient way. If you restrict the programmer he will either drop the whole feature for the sake of convenience or invent ugly workarounds, like the following template based type safe enum. It will have a some overhead when compiled without optimization.
template<class _Enum>
class type_safe_enum
{
private:
_Enum m_EnumValue;
operator int();
public:
inline operator _Enum() const { return m_EnumValue; }
inline void operator =(_Enum x) { m_EnumValue = x; }
};
enum _MY_ENUM
{
Value1,
Value2
};
enum _MY_ENUM2
{
Value3,
Value4
};
typedef type_safe_enum<_MY_ENUM> MY_ENUM;
void TestMyEnum()
{
MY_ENUM myEnum;
int x;
myEnum = Value1; // ok
// myEnum = Value3; // compilation error
// myEnum = 0; // compilation error
// x = myEnum; // compilation error
}

"using" directive for declarator of scoped enum? [duplicate]

I am using a scoped enum to enumerate states in some state machine that I'm implementing. For example, let's say something like:
enum class CatState
{
sleeping,
napping,
resting
};
In my cpp file where I define a state transition table, I would like to use something equivalent to using namespace X so that I don't need to prefix all my state names with CatState::. In other words, I'd like to use sleeping instead of CatState::sleeping. My transition table has quite a few columns, so avoiding the CatState:: prefix would keep things more compact and readable.
So, is there a way to avoid having to type CatState:: all the time?
Yeah, yeah, I'm already aware of the pitfalls of using namespace. If there's an equivalent for strongly-typed enums, I promise to only use it inside a limited scope in my cpp implementation file, and not for evil.
So, is there a way to avoid having to type CatState:: all the time?
Not before C++20. Just as there's no equivalent for having to type ClassName:: for static class members. You can't say using typename ClassName and then get at the internals. The same goes for strongly typed enums.
C++20 adds the using enum X syntax, which does what it looks like.
You can of course not use enum class syntax, just using regular enums. But then you lose strong typing.
It should be noted that one of the reasons for using ALL_CAPS for weakly typed enums was to avoid name conflicts. Once we have full scoping and strong typing, the name of an enum is uniquely identified and cannot conflict with other names. Being able to bring those names into namespace scope would reintroduce this problem. So you would likely want to use ALL_CAPS again to help disambiguate the names.
So the short answer is no, but fortunately this is going to change in a recently finalized feature set of C++20. According to this accepted proposal you will be able to do the following:
enum class CatState
{
sleeping,
napping,
resting
};
std::string getPurr(CatState state)
{
switch (state)
{
using enum CatState;
// our states are accessible without the scope operator from now on
case sleeping: return {}; // instead of "case CatState::sleeping:"
case napping: return "purr";
case resting: return "purrrrrr";
}
}
You might consider using a typedef to shorten the qualified names:
typedef CatState C;
Or, if the columns are repetitive in a way that they can be generated easily, you might consider using a macro to generate each row in the table, which can lead to very concise (and easier to read) code.
Nicol's answer is correct: the language is designed to make you always qualify scoped enumerators (except in the enum { } scope itself).
However, here is a technique I came up with for "scoped" enumerators that are unscoped within chosen classes. Technically, the enumerators are unscoped, so they will still convert implicitly to int. (Not "strongly-typed" as you put it.) Nevertheless, in the idiom they are accessed using the scope operator after a true enum name, so syntactically there isn't a difference — and therefore it requires C++11.
#define IMPORTABLE_ENUM( TYPENAME, ... ) \
\
struct import_ ## TYPENAME { \
enum TYPENAME { \
__VA_ARGS__ \
}; \
}; \
\
typedef import_ ## TYPENAME :: TYPENAME TYPENAME;
// usage:
IMPORTABLE_ENUM ( duck, huey, dewey, louie )
duck d = duck::dewey; // can't use unscoped enumerators here
struct duck_madness : private import_duck { // but inside a derived class
duck who_did_it() { return huey; } // qualification is unnecessary
};
I would also love to have this possibility and I find the limitation quite annoying. It's usually best to have the programmer decide which features he wants to use. Either explicit scoping or the more convenient way. If you restrict the programmer he will either drop the whole feature for the sake of convenience or invent ugly workarounds, like the following template based type safe enum. It will have a some overhead when compiled without optimization.
template<class _Enum>
class type_safe_enum
{
private:
_Enum m_EnumValue;
operator int();
public:
inline operator _Enum() const { return m_EnumValue; }
inline void operator =(_Enum x) { m_EnumValue = x; }
};
enum _MY_ENUM
{
Value1,
Value2
};
enum _MY_ENUM2
{
Value3,
Value4
};
typedef type_safe_enum<_MY_ENUM> MY_ENUM;
void TestMyEnum()
{
MY_ENUM myEnum;
int x;
myEnum = Value1; // ok
// myEnum = Value3; // compilation error
// myEnum = 0; // compilation error
// x = myEnum; // compilation error
}

Reasonable key types for map used to set properties of related classes?

I'm planning to write a code with classes that have inheritance relationships like the following and have various properties that are associated with material types:
Abstract base class Foo. No properties associated with it.
Foo1GeneralElastic inherits from class Foo and has the properties associated with a possibly anisotropic elastic material.
Foo2GeneralElastic also inherits from class Foo and has the same kinds of material properties as Foo1GeneralElastic, but is otherwise different.
Foo1PiezoElastic inherits from Foo1GeneralElastic and has both piezoelectric properties as well as generic elastic ones.
Foo1IsotropicElastic inherits from Foo1GeneralElastic, but does not share its properties.
I decided that the abstract base class would have one or more methods that take a map of type MyPropMap, defined as:
typedef std::map<PropertyLabel,std::vector<double> > MyPropMap
I have a few different options on what the PropertyLabel type could be, and I'm trying to weigh the pros and cons of each:
Have the PropertyLabel be an enum: This would be lightweight, but it would basically be a bag of labels for all the different properties of every material that I'm considering.
Have the PropertyLabel be just an int: Here, I'd have separate header files for each material type, each of which would contain definition of static integer constants that would be labels for the relevant material properties. For example, MatPropKeyGenElastic.hpp would define the integer constant ELASTICITY_MATRIX, MatPropKeyIsotropicElastic.hpp would define the constants ELASTIC_MODULUS and POISSONS_RATIO, and MatPropKeyPiezoElastic.hpp would #include the file MatPropKeyGenElastic.hpp and additionally define the constant PIEZO_CONST_MATRIX.
The tricky thing would be to make sure that none of the constants that could be used together would have the same values. That could be accomplished by generating the header files with a script that would set the values of these constants to unique values.
Have the PropertyLabel be a std::string From here I could take things a few different ways. I could just have string literals like "ELASTICITY_MATRIX" in the code and rely on these literals never being misspelled---an error that would be caught at run-time rather than compile time. I could define string constants in way analogous to the scheme above for integer constants, and the task of keeping the constants unique would be trivial: just set the value of ELASTICITY_MATRIX to "ELASTICITY_MATRIX", the value of POISSONS_RATIO to "POISSONS_RATIO", etc.
The catch I see with that, aside from the extra overhead, is that I've seen horror stories relating to global static constants of non-PODs, such as those in the comments in the topics non-integral constants and Defining class string constants in C++?. I suppose that I could have the global static constants be const char[] arrays, which are PODs that would be implicitly converted into std::strings when used as map keys (and, no, I am not planning on letting the map key itself be const char*). I could also define the string literals with the preprocessor, but then I couldn't keep them within a namespace.
Would you recommend any of the above approaches? Are there hidden traps in them that I hadn't noticed? Are there still other approaches that you would recommend?
I don't recommend to use strings. It's too expensive for such simple task. I vote for enum.
But if it looks too ugly to you to keep all label constants in a single place, you could elaborate more complex approach - use a composite key like pair of two numbers - (class ID, property ID).
Both could be defined as enums, maybe nested. Moreover, class ID could be generated automatically - e.g. using reinterpret_cast on std::type_info pointer or just using std::type_info pointer or std::type_index if supported. Illustrating idea with code:
// PropertyLabel type, could be used as associative container key
struct PropertyLabel: std::pair<const std::type_info*, int>
{
// Template ctor allows implicit conversion from enums
// (actually not only from enums but from any int-compatible types)
// Uncomment explicit keyword if implicit conversions scares you and use
// explicit conversion syntax - PropertyLabel(smth).
template <typename T> /*explicit*/ PropertyLabel(T label):
std::pair<const std::type_info*, int>(&typeid(T), label)
{
}
};
// First property holder
class PropertyUser1
{
public:
enum Labels
{
eProperty1,
eProperty2,
eProperty3,
};
};
// Second property holder
class PropertyUser2
{
public:
enum Labels
{
eProperty1,// Due to class scope you could use same names for different properties
eProperty2,
eProperty3,
};
};
// Usage. A bit dangerous due to implicit conversions, but intuitive and handy:
MyPropMap properties;
properties[PropertyUser1::eProperty1].push_back(42.0);
properties[PropertyUser2::eProperty1].push_back(42.42);
// Will be with explicit ctor:
// properties[PropertyLabel(PropertyUser1::eProperty1)].push_back(42.0);
// properties[PropertyLabel(PropertyUser2::eProperty1)].push_back(42.42);
Looks like it could be improved with more type safety eliminating possibility of using non-enum types like int, e.g. disabling calls like PropertyLabel(42). But this is just to illustrate idea.
I just realized a relatively simple solution that would give me pretty much what I want without too much fuss. For any particular instance of the MyPropMap type, I'm dealing with the properties of one particular kind of material: isotropic elastic, piezoelectric, anisotropic elastic, and so on. Given this, I can wrap the enums corresponding to each material type in its own namespace and put them in the appropriate header file, so for example,
// MatPropKey/IsotropicElastic.hpp:
namespace IsotropicElastic {
enum { ELASTIC_MODULUS, POISSONS_RATIO };
}
// MatPropKey/GenElastic.hpp
namespace GenElastic {
enum { ELASTICITY_MATRIX }
}
// MatPropKey/PiezoElastic.hpp
namespace PiezoElastic {
enum { PIEZO_CONST_MATRIX, ELASTICITY_MATRIX }
}
There is some redundancy here, but I can live with that. So long as I stick to the above convention, then within each namespace, the enum values are unique, and so long as I only use the enum values within a particular namespace for each instance of MyPropMap---which I want to do anyway---I'm fine. (Realistically, I'd also want to wrap each of these namespaces within a common MPKey namespace.) Of course, this isn't foolproof. A sufficiently creative fool could, for example, decide to #include both GenElastic.hpp and PiezoElastic.hpp and then use GenElastic::ELASTICITY_MATRIX with the PiezoElastic::PIEZO_CONST_MATRIX. Bad things could then happen. Still, the code communicates how the named constants are supposed to be grouped, and avoiding unwanted name clashes is trivial.
Wish I thought of it earlier.
After some thought, I realized a few things:
It's better to wrap the map within a class, so that I have a bit more control over how it is written.
Even the wrapped map is generic and has to be able to accommodate any material parameter type, so there's only so much compile-type safety that I can provide.
Given this, I decided to design a MatProp class roughly as follows:
#include <vector>
#include <map>
class MatProp {
public:
// Skipping the constructor details ...
void setProp_Raw(int propId, double val);
void getProp_Raw(int propId, double & val) const;
void setProp_Raw(int propId, const std::vector<double> & vals);
void getProp_Raw(int propId, std::vector<double> & vals) const;
// More overloaded set/get funcs for complex scalars and vectors ...
private:
// The typedef allows me to write MatPropMap_::iterator, etc. in the
// implementation of the member functions, which is handy if, say,
// I want to swap the std::map for an unordered_map later on.
typedef std::map<PropertyLabel,std::vector<double> > MatPropMap_;
MatPropMap_ matPropMap_;
};
The set/get functions are suffixed with _Raw because it's easy to put in a wrong combination of property ID and value. I could pass in information to the constructor of MatProp so that the inputs to these functions could be validated at run time, but setting that up could get clunky and make the class harder to use. To add some extra safety, I can do this, for example:
void setIsotropicLinearElasticParameter(MatProps mProp,
ElasPropEnum propId, // ELASTIC_MODULUS and POISSONS_RATIO are the
// *only* valid values of this parameter.
double val) {
mProp.setParam_Raw(propId, val);
}
The function is simple, but I'm declaring clearly that (1) only two keys are allowed and (2) they really are supposed to be of type double. The interface isn't totally foolproof, but it's fairly easy to use correctly and takes some effort to use wrong. FWIW, a similar thing was done here: http://blog.knatten.org/2010/04/23/make-apis-hard-to-use-incorrectly/.

Equivalent of "using namespace X" for scoped enumerations?

I am using a scoped enum to enumerate states in some state machine that I'm implementing. For example, let's say something like:
enum class CatState
{
sleeping,
napping,
resting
};
In my cpp file where I define a state transition table, I would like to use something equivalent to using namespace X so that I don't need to prefix all my state names with CatState::. In other words, I'd like to use sleeping instead of CatState::sleeping. My transition table has quite a few columns, so avoiding the CatState:: prefix would keep things more compact and readable.
So, is there a way to avoid having to type CatState:: all the time?
Yeah, yeah, I'm already aware of the pitfalls of using namespace. If there's an equivalent for strongly-typed enums, I promise to only use it inside a limited scope in my cpp implementation file, and not for evil.
So, is there a way to avoid having to type CatState:: all the time?
Not before C++20. Just as there's no equivalent for having to type ClassName:: for static class members. You can't say using typename ClassName and then get at the internals. The same goes for strongly typed enums.
C++20 adds the using enum X syntax, which does what it looks like.
You can of course not use enum class syntax, just using regular enums. But then you lose strong typing.
It should be noted that one of the reasons for using ALL_CAPS for weakly typed enums was to avoid name conflicts. Once we have full scoping and strong typing, the name of an enum is uniquely identified and cannot conflict with other names. Being able to bring those names into namespace scope would reintroduce this problem. So you would likely want to use ALL_CAPS again to help disambiguate the names.
So the short answer is no, but fortunately this is going to change in a recently finalized feature set of C++20. According to this accepted proposal you will be able to do the following:
enum class CatState
{
sleeping,
napping,
resting
};
std::string getPurr(CatState state)
{
switch (state)
{
using enum CatState;
// our states are accessible without the scope operator from now on
case sleeping: return {}; // instead of "case CatState::sleeping:"
case napping: return "purr";
case resting: return "purrrrrr";
}
}
You might consider using a typedef to shorten the qualified names:
typedef CatState C;
Or, if the columns are repetitive in a way that they can be generated easily, you might consider using a macro to generate each row in the table, which can lead to very concise (and easier to read) code.
Nicol's answer is correct: the language is designed to make you always qualify scoped enumerators (except in the enum { } scope itself).
However, here is a technique I came up with for "scoped" enumerators that are unscoped within chosen classes. Technically, the enumerators are unscoped, so they will still convert implicitly to int. (Not "strongly-typed" as you put it.) Nevertheless, in the idiom they are accessed using the scope operator after a true enum name, so syntactically there isn't a difference — and therefore it requires C++11.
#define IMPORTABLE_ENUM( TYPENAME, ... ) \
\
struct import_ ## TYPENAME { \
enum TYPENAME { \
__VA_ARGS__ \
}; \
}; \
\
typedef import_ ## TYPENAME :: TYPENAME TYPENAME;
// usage:
IMPORTABLE_ENUM ( duck, huey, dewey, louie )
duck d = duck::dewey; // can't use unscoped enumerators here
struct duck_madness : private import_duck { // but inside a derived class
duck who_did_it() { return huey; } // qualification is unnecessary
};
I would also love to have this possibility and I find the limitation quite annoying. It's usually best to have the programmer decide which features he wants to use. Either explicit scoping or the more convenient way. If you restrict the programmer he will either drop the whole feature for the sake of convenience or invent ugly workarounds, like the following template based type safe enum. It will have a some overhead when compiled without optimization.
template<class _Enum>
class type_safe_enum
{
private:
_Enum m_EnumValue;
operator int();
public:
inline operator _Enum() const { return m_EnumValue; }
inline void operator =(_Enum x) { m_EnumValue = x; }
};
enum _MY_ENUM
{
Value1,
Value2
};
enum _MY_ENUM2
{
Value3,
Value4
};
typedef type_safe_enum<_MY_ENUM> MY_ENUM;
void TestMyEnum()
{
MY_ENUM myEnum;
int x;
myEnum = Value1; // ok
// myEnum = Value3; // compilation error
// myEnum = 0; // compilation error
// x = myEnum; // compilation error
}