I am abstracting my problem now but I am in this kind of situation.
Let's say I have 2 enums that are in the same namespace.
namespace some_namespace {
enum class Something{
S,
O,
M,
E,
T,
H,
I,
N,
G
};
enum class Else{
E,
L,
S
};
}
Now let's create 2 structs which have as a static field some value of these enums.
struct SomeStruct{
static constexpr int enumValue = static_cast<int>(some_namespace::Something::T);
};
struct AnotherStruct {
static constexpr int enumValue = static_cast<int>(some_namespace::Something::O);
};
How can I check whether the enumValues of this 2 structs are from the same enum class or not? I think I shall give some values to my enum fields and use some bitwise operator on enum values to distinguish? Can someone help? thanks)
Using just the static_casted enumValue it is not possible to distinguish the originating enum(as pointed out by #Sam). What you can instead do is introduce a new field that stores the underlying enum class type and leverage that to make the distinction.
enum class E1{ One, Two };
enum class E2{Three, Four };
struct SomeStruct{
static constexpr int enumValue = static_cast<int>(E1::One);
using UnderlyingT = E1;
};
struct AnotherStruct {
static constexpr int enumValue = static_cast<int>(E2::Three);
using UnderlyingT = E2;
};
static_assert(!std::is_same_v<SomeStruct::UnderlyingT, AnotherStruct::UnderlyingT>);
Code Link
As already indicated in the comments, you don't want to convert your enum to an int if you still want to know the type.
There might be some reasons to keep the type and the scoping while wanting to implicit conversion to the underlying type.
What you could do is to wrap the enum into a class that converts to both the underlying type AND the actual enum.
#include <type_traits>
template<typename TEnum>
class ImplicitEnumConverter final
{
public:
TEnum e;
using TUnderlyingType = std::underlying_type_t<TEnum>;
constexpr ImplicitEnumConverter(TEnum e) : e{e} {}
constexpr operator TUnderlyingType() const noexcept
{
return static_cast<TUnderlyingType>(e);
}
constexpr operator TEnum() const noexcept
{
return e;
}
};
struct SomeStruct{
static constexpr auto enumValue = ImplicitEnumConverter{some_namespace::Something::T};
};
Code at compiler-explorer
This way, you are able to keep all the type-safe information where this is relevant AND you are able to convert it implicitly to an int.
The answer was simpler than I thought.
So I declare enum like this.
namespace some_namespace {
enum class Something{
S = 0,
O = 2,
M = 4,
E = 6,
T = 8,
H = 10,
I = 12,
N = 14,
G = 16
};
enum class Else{
E = 1,
L = 3,
S = 5
};
}
And then this leads me to check whether two integer values have the same parity or not . Thus
if((SomeStruct::enum_value + AnotherStruct::enum_value) % 2 == 0) {
// Same enum
} else {
// not same enum.
}
Related
While looking for a generic way to perform an enum cast, I stumbled across an interesting solution posted here. In order to strengthen the underlying enum data types, I tried to replace the conventional enum with a C++11 enum class as follows:
// generic code
#include <algorithm>
template <typename T>
struct enum_traits {};
template<typename T, size_t N>
T *endof(T(&ra)[N]) {
return ra + N;
}
template<typename T, typename ValType>
T check(ValType v) {
typedef enum_traits<T> traits;
const T *first = traits::enumerators;
const T *last = endof(traits::enumerators);
if (traits::sorted) { // probably premature optimization
if (std::binary_search(first, last, v)) return T(v);
}
else if (std::find(first, last, v) != last) {
return T(v);
}
throw "exception";
}
/*
// "enhanced" definition of enum
enum e {
x = 1,
y = 4,
z = 10,
};
*/
// new C++11 enum class
enum class e : int {
x = 1,
y = 4,
z = 10,
};
template<>
struct enum_traits<e> {
static const e enumerators[];
static const bool sorted = true;
};
// must appear in only one TU,
// so if the above is in a header then it will need the array size
const e enum_traits<e>::enumerators[] = { e::x, e::y, e::z };
// usage
int main() {
e good = check<e>(1);
e bad = check<e>(2);
}
However, this leads to a crash during the compilation process (error C1001: An internal error has occurred in the compiler.). I can't seem to figure out what's causing this, but my guess is that the std::find() and/or std::binary_search() functions are having problems dealing with the enum class. Has someone experienced a similar issue yet?
With an enum Foo::Values and a class Bar outside of Foo, can I inject all values of the enum into class scope without redefining the type?
namespace Foo{
enum Values{
zero, one, two
};
}
struct Bar{
typedef Foo::Values Values; //Doesn't work, but is what I'd like to do
using Foo::Values; //Or this
}
So that these are valid:
Foo::Values val = Bar::zero;
assert(std::is_same<Foo::Values, Bar::Values>::value);
Is this possible?
This way:
using Values = Foo::Values;
Extracting the values is possible only one by one:
static constexpr Values zero = Foo::zero;
static constexpr Values one = Foo::one;
static constexpr Values two = Foo::two;
Check:
#include <iostream>
#include <type_traits>
namespace Foo {
enum Values { zero, one, two };
}
struct Bar {
using Values = Foo::Values;
static constexpr Values zero = Foo::zero;
static constexpr Values one = Foo::one;
static constexpr Values two = Foo::two;
};
int main() {
Foo::Values val = Bar::zero;
std::cout << std::is_same<Foo::Values, Bar::Values>::value;
}
Output:
1
Consider the following code:
enum A : unsigned { a = 1, b = 2, c = 4 };
class B
{
friend constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }
};
template <A a>
class C
{
};
int main()
{
C<a|c> c;
}
When compiled with g++ (4.8.1, -std=c++1), I get the following error:
test.C: In function ‘int main()’:
test.C:16:12: error: invalid conversion from ‘unsigned int’ to ‘A’ [-fpermissive]
C<a|c> c;
Which tells me that the operator is not being found. However, if the code is changed to:
enum A : unsigned { a = 1, b = 2, c = 4 };
constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }
template <A a>
class C
{
};
int main()
{
C<a|c> c;
}
Then it compiles and runs fine. Is the error in the first case a compiler error, or I do misunderstand something? I would like to use the method of Boost.Operators to easily define operators by declaring a class with base classes from templates which define the operators, but this result precludes that in this case.
Thanks for any help.
Another way to solve it (other than jogojapan already mentioned), is to simply declare the friend function outside the scope.
enum A : unsigned { a = 1, b = 2, c = 4 };
//declaration
constexpr A operator|(A a1, A a2);
class B
{
//definition inside, ok.
friend constexpr A operator|(A a1, A a2)
{ return A(unsigned(a1) | unsigned(a2)); }
};
template <A a>
class C
{
};
int main()
{
C<a|c> c;
}
Okay, I took another approach, and here's code which solves my problem:
template <typename UNSIGNED>
struct BitwiseEnum
{
enum class Enum : UNSIGNED
{
};
constexpr static Enum value(unsigned bit)
{
return Enum(UNSIGNED(1) << bit);
}
friend constexpr Enum operator|(Enum a, Enum b)
{
return Enum(UNSIGNED(a)|UNSIGNED(b));
}
friend constexpr Enum operator&(Enum a, Enum b)
{
return Enum(UNSIGNED(a)&UNSIGNED(b));
}
friend constexpr Enum operator~(Enum a)
{
return Enum(~UNSIGNED(a));
}
};
class MyMask : public BitwiseEnum<unsigned long>
{
};
typedef MyMask::Enum Mask;
constexpr static Mask a = MyMask::value(0);
constexpr static Mask b = MyMask::value(1);
constexpr static Mask c = MyMask::value(2);
constexpr static Mask d = MyMask::value(3);
template <Mask A>
class B
{
};
int main()
{
B<a|b> test;
}
Now, when I defined a lot of enums like "MyMask", it can be done fairly simply, without much more code than a simply defined enum would have. And it behaves as one would "expect" from a bit field enum, can be used in strongly type checked template arguments, etc.
Is there a generic way to cast int to enum in C++?
If int falls in range of an enum it should return an enum value, otherwise throw an exception. Is there a way to write it generically? More than one enum type should be supported.
Background: I have an external enum type and no control over the source code. I'd like to store this value in a database and retrieve it.
The obvious thing is to annotate your enum:
// generic code
#include <algorithm>
template <typename T>
struct enum_traits {};
template<typename T, size_t N>
T *endof(T (&ra)[N]) {
return ra + N;
}
template<typename T, typename ValType>
T check(ValType v) {
typedef enum_traits<T> traits;
const T *first = traits::enumerators;
const T *last = endof(traits::enumerators);
if (traits::sorted) { // probably premature optimization
if (std::binary_search(first, last, v)) return T(v);
} else if (std::find(first, last, v) != last) {
return T(v);
}
throw "exception";
}
// "enhanced" definition of enum
enum e {
x = 1,
y = 4,
z = 10,
};
template<>
struct enum_traits<e> {
static const e enumerators[];
static const bool sorted = true;
};
// must appear in only one TU,
// so if the above is in a header then it will need the array size
const e enum_traits<e>::enumerators[] = {x, y, z};
// usage
int main() {
e good = check<e>(1);
e bad = check<e>(2);
}
You need the array to be kept up to date with e, which is a nuisance if you're not the author of e. As Sjoerd says, it can probably be automated with any decent build system.
In any case, you're up against 7.2/6:
For an enumeration where emin is the
smallest enumerator and emax is the
largest, the values of the enumeration
are the values of the underlying type
in the range bmin to bmax, where bmin
and bmax are, respectively, the
smallest and largest values of the
smallest bit-field that can store emin
and emax. It is possible to define an
enumeration that has values not
defined by any of its enumerators.
So if you aren't the author of e, you may or may not have a guarantee that valid values of e actually appear in its definition.
Ugly.
enum MyEnum { one = 1, two = 2 };
MyEnum to_enum(int n)
{
switch( n )
{
case 1 : return one;
case 2 : return two;
}
throw something();
}
Now for the real question. Why do you need this? The code is ugly, not easy to write (*?) and not easy to maintain, and not easy to incorporate in to your code. The code it telling you that it's wrong. Why fight it?
EDIT:
Alternatively, given that enums are integral types in C++:
enum my_enum_val = static_cast<MyEnum>(my_int_val);
but this is even uglier that above, much more prone to errors, and it won't throw as you desire.
If, as you describe, the values are in a database, why not write a code generator that reads this table and creates a .h and .cpp file with both the enum and a to_enum(int) function?
Advantages:
Easy to add a to_string(my_enum) function.
Little maintenance required
Database and code are in synch
No- there's no introspection in C++, nor is there any built in "domain check" facility.
What do you think about this one?
#include <iostream>
#include <stdexcept>
#include <set>
#include <string>
using namespace std;
template<typename T>
class Enum
{
public:
static void insert(int value)
{
_set.insert(value);
}
static T buildFrom(int value)
{
if (_set.find(value) != _set.end()) {
T retval;
retval.assign(value);
return retval;
}
throw std::runtime_error("unexpected value");
}
operator int() const { return _value; }
private:
void assign(int value)
{
_value = value;
}
int _value;
static std::set<int> _set;
};
template<typename T> std::set<int> Enum<T>::_set;
class Apples: public Enum<Apples> {};
class Oranges: public Enum<Oranges> {};
class Proxy
{
public:
Proxy(int value): _value(value) {}
template<typename T>
operator T()
{
T theEnum;
return theEnum.buildFrom(_value);
}
int _value;
};
Proxy convert(int value)
{
return Proxy(value);
}
int main()
{
Apples::insert(4);
Apples::insert(8);
Apples a = convert(4); // works
std::cout << a << std::endl; // prints 4
try {
Apples b = convert(9); // throws
}
catch (std::exception const& e) {
std::cout << e.what() << std::endl; // prints "unexpected value"
}
try {
Oranges b = convert(4); // also throws
}
catch (std::exception const& e) {
std::cout << e.what() << std::endl; // prints "unexpected value"
}
}
You could then use code I posted here to switch on values.
You should not want something like what you describe to exist, I fear there are problems in your code design.
Also, you assume that enums come in a range, but that's not always the case:
enum Flags { one = 1, two = 2, four = 4, eigh = 8, big = 2000000000 };
This is not in a range: even if it was possible, are you supposed to check every integer from 0 to 2^n to see if they match some enum's value?
If you are prepared to list your enum values as template parameters you can do this in C++ 11 with varadic templates. You can look at this as a good thing, allowing you to accept subsets of the valid enum values in different contexts; often useful when parsing codes from external sources.
Perhaps not quite as generic as you'd like, but the checking code itself is generalised, you just need to specify the set of values. This approach handles gaps, arbitrary values, etc.
template<typename EnumType, EnumType... Values> class EnumCheck;
template<typename EnumType> class EnumCheck<EnumType>
{
public:
template<typename IntType>
static bool constexpr is_value(IntType) { return false; }
};
template<typename EnumType, EnumType V, EnumType... Next>
class EnumCheck<EnumType, V, Next...> : private EnumCheck<EnumType, Next...>
{
using super = EnumCheck<EnumType, Next...>;
public:
template<typename IntType>
static bool constexpr is_value(IntType v)
{
return v == static_cast<typename std::underlying_type<EnumType>::type>(V) || super::is_value(v);
}
EnumType convert(IntType v)
{
if (!is_value(v)) throw std::runtime_error("Enum value out of range");
return static_cast<EnumType>(v);
};
enum class Test {
A = 1,
C = 3,
E = 5
};
using TestCheck = EnumCheck<Test, Test::A, Test::C, Test::E>;
void check_value(int v)
{
if (TestCheck::is_value(v))
printf("%d is OK\n", v);
else
printf("%d is not OK\n", v);
}
int main()
{
for (int i = 0; i < 10; ++i)
check_value(i);
}
C++0x alternative to the "ugly" version, allows for multiple enums. Uses initializer lists rather than switches, a bit cleaner IMO. Unfortunately, this doesn't work around the need to hard-code the enum values.
#include <cassert> // assert
namespace // unnamed namespace
{
enum class e1 { value_1 = 1, value_2 = 2 };
enum class e2 { value_3 = 3, value_4 = 4 };
template <typename T>
int valid_enum( const int val, const T& vec )
{
for ( const auto item : vec )
if ( static_cast<int>( item ) == val ) return val;
throw std::exception( "invalid enum value!" ); // throw something useful here
} // valid_enum
} // ns
int main()
{
// generate list of valid values
const auto e1_valid_values = { e1::value_1, e1::value_2 };
const auto e2_valid_values = { e2::value_3, e2::value_4 };
auto result1 = static_cast<e1>( valid_enum( 1, e1_valid_values ) );
assert( result1 == e1::value_1 );
auto result2 = static_cast<e2>( valid_enum( 3, e2_valid_values ) );
assert( result2 == e2::value_3 );
// test throw on invalid value
try
{
auto result3 = static_cast<e1>( valid_enum( 9999999, e1_valid_values ) );
assert( false );
}
catch ( ... )
{
assert( true );
}
}
Why do people use enums in C++ as constants when they can use const?
Bruce Eckel gives a reason in Thinking in C++:
In older versions of C++, static const was not supported inside classes. This meant that const was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untagged enum with no instances. An enumeration must have all its values established at compile time, it’s local to the class, and its values are available for constant expressions. Thus, you will commonly see:
#include <iostream>
using namespace std;
class Bunch {
enum { size = 1000 };
int i[size];
};
int main() {
cout << "sizeof(Bunch) = " << sizeof(Bunch)
<< ", sizeof(i[1000]) = "
<< sizeof(int[1000]) << endl;
}
Enums are distinct types, so you can do type-oriented things like overloading with them:
enum Color { Red,Green,Blue };
enum Size { Big,Little };
void f( Color c ) {
}
void f( Size s ) {
}
int main() {
f( Red );
f( Big );
}
An enumeration implies a set of related constants, so the added information about the relationship must be useful in their model of the problem at hand.
There's a historical reason too when dealing with template metaprogramming. Some compilers could use values from an enum, but not a static const int to instantiate a class.
template <int N>
struct foo
{
enum { Value = foo<N-1>::Value + N };
};
template <>
struct foo<0>
{
enum { Value = 0; }
};
Now you can do it the more sensible way:
template <int N>
struct foo
{
static const int Value = foo<N-1>::Value + N;
};
template <>
struct foo<0>
{
static const int Value = 0;
};
Another possible reason, is that a static const int may have memory reserved for it at runtime, whereas an enum is never going to have an actual memory location reserved for it, and will be dealt at compile time. See this related question.
Enums are more descriptive when used. Consider:
int f(int fg, int bg)
versus
int f(COLOR fg, COLOR bg)
In addition, enums give a bit more type-safety, because
integers are not implicitly convertible to enum types
enum of one type is not implicitly convertible to enum of another type
I like the automatic behavior that can be used with enums, for example:
enum {NONE, START, HEY, HO, LAST};
Then it is easy to loop until LAST, and when a new state (or whatever is represented) is added, the logic adapts.
for (int i = NONE; i < LAST; i++)
{
// Do stuff...
}
Add something...
enum {NONE, START, HEY, WEE, HO, LAST};
The loop adapts...
Before compiler vendors implemented the ISO/IEC 14882:1998 C++ standard, this code to define a constant in a class scope resulted in a compile error:
class Foo {
static const int MAX_LEN = 80;
...
};
If the constant is an integer type, a kludgy work around is define it in an enum inside the class:
class Foo {
enum {
MAX_LEN = 80
};
...
};
enums also can be used as a type name. So you can define a function that takes an enum as a parameter, which makes it more clear what kinds of values should be given as arguments to the function, as compared to having the values defined as const variables and the function accepting just "int" as an argument.
Consider:
enum my_new_fangled_type {
baz = 0,
meh = 1
};
void foo (my_new_fangled_type bar) // bar can be a value listed in the enum
{
...
}
versus:
int const baz = 0;
int const meh = 1;
void foo (int bar) // what are valid values for bar?
{
...
}
Some debuggers will show the enumeration name instead of its value when debugging. This can be very helpful. I know that I would rather see day_of_week = MONDAY than day_of_week = 1.
It's partly because older compilers did not support the declaration of a true class constant
class C
{
const int ARealConstant = 10;
};
so had to do this
class C
{
enum { ARealConstant = 10 };
};
For this reason, many portable libraries continue to use this form.
The other reason is that enums can be used as a convenient syntactic device to organise class constants into those that are related, and those that are not
class DirectorySearcher
{
enum options
{
showFiles = 0x01,
showDirectories = 0x02,
showLinks = 0x04,
};
};
vs
class Integer
{
enum { treatAsNumeric = true };
enum { treatAsIntegral = true };
enum { treatAsString = false };
};
Using an enum documents the valid choices in a terse manner and allows the compiler to enforce them.
If they are using enum store global constants, like Pi, for example, then I don't know what their goal is.
One reason is that const requires more typing:
enum { Val1, Val2, Val3 };
...versus...
const int Val1=0, Val2=1, Val3=2;