Is there a way, at compile-time, to verify that a given
value is within the values of a given enum, thus valid?
enum myenum { val1 = 10, val2 = 30, val3 = 45 }
template <myenum t>
class myClass
{ ... }
myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; //compiles, NOT OK!
Using a second template non-type boolean parameter would be useful in there, and the value of that boolean would be given by a meta-function, that given a value would verify that the value is within the values of myenum.
I looked through various enum related question, like how to iterate an enum, and it seems it can't be done.
enum myenum { val1 = 10, val2 = 30, val3 = 45 };
template<myenum e> struct is_valid_myenum { static const bool value = (e==val1 || e==val2 || e==val3); };
template<myenum t>
class myClass
{
static_assert(is_valid_myenum<t>::value, "t must be a valid enum value");
};
myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; // fails, OK
If you really, really want to avoid the duplication (and aren't interested in using some external tool to generate sourcecode) you can resort to macro hackery.
#define LIST \
ITEM(val1,10)\
ITEM(val2,30)\
ITEM(val3,45)
#define ITEM(NAME,VALUE) NAME = VALUE,
enum myenum { LIST };
#undef ITEM
#define ITEM(NAME,VALUE) e==NAME ||
template<myenum e> struct is_valid_myenum { static const bool value = ( LIST false ); };
template<myenum t>
class myClass
{
static_assert(is_valid_myenum<t>::value, "t must be a valid enum value");
};
myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; // fails, OK
You can never prevent other developers to shoot in their own foot. You can never win. Just ensure your API does not make it easy.
If he takes an invalid value, casts it, and then passes it to you, it is purely his problem. This is the same kind of problem as if you provide him a function taking a pointer of type T* as parameter, but he takes some random data (of arbitrary type), casts it to T* and passes it in.
That's how casting works: The person who does the cast is responsible to guarantee that the casted expression can be safely interpreted as value of the type he casts to.
Short of redeclaring all your information in metaprogramming form, it cannot be done. However, you could for instance do:
enum myenum { val1 = 10, val2 = 30, val3 = 45 };
typedef vector_c< myenum, val1, val2, val3 > typed_myenum;
typedef
contains< typed_myenum, integral_c< myenum, val >::value
val_found;
Using functionality from Boost.MPL, although the actual syntax might be a bit off.
There are no ways to check that a value is within a valid range of an enum at run time, less at compile time.
The only way to check is to brute force check for every value. Something like this:
enum lala
{
A = 10,
B = 20,
C = 30
};
template< int value >
struct T
{
static_assert( (value == A) || (value == B ) || (value == C), "wrong value" );
};
int main()
{
T< 10 > t10;
T< 20 > t20;
T< 25 > t25;
T< 30 > t30;
(void)t10;(void)t20;(void)t25;(void)t30;
}
If the enum's name is not important for you, maybe you can just transfer it to an array, such as:
const int myenum[]={10,30,45}
then use an index to reference them from the myenum.
template<unsigned int t>
class myClass
{
static_assert(t < sizeof(myenum)/sizeof(int), "t must be a valid enum index");
int val=myenum[t];
...
};
Related
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.
}
I have a requirement where there's a enum and there are template functions defined for all the possible enum combinations upto length l.
Say the enum is
Enum typenum {A, B, C}
And all these template functions are defined and available at runtime (i.e, compiler creates these functions at the compile time)
Alpha<A>::f()
Alpha<B>::f()
Alpha<C>::f()
Alpha<A,A>::f()
Alpha<A,B>::f()
Alpha<A,C>::f()
Alpha<B,A>::f()
Alpha<B,B>::f()
Alpha<B,C>::f()
Alpha<C,A>::f()
Alpha<C,B>::f()
Alpha<C,C>::f()
and combination of 3 enums, 4 enums...
Now I've to choose the right function as per an input vector
void f(vector<enum> eVec){
Alpha::f<eVec[0], eVec[1],... eVec[eVec.size() - 1]>() // <-------
How do I do this? One way to do this would be to define for every size. Eg:
if(eVec.size() == 1)
Alpha<eVec[0]>::f()
else if(eVec.size() == 2)
Alpha<eVec[0], eVec[1]>::f()
This won't scale though. Is there any elegant, scalable way of doing this.
And all these template functions are defined and available at runtime (i.e, compiler creates these functions at the compile time)
Are you sure it's a good idea?
Because, if you want select run-time template values, you have to implement, compile time, all possible Alpha<typeNumsValues...>::f() combinations.
That is impossible if you don't impose a length limit for the variadic list, but is very computationally expensive also when there is relatively low limit.
Anyway... suppose you have an enum as follows
enum typeEnum { A, B, C };
and variadic template Alpha class, with typeEnum template values and a static method f() as follows
template <typeEnum ...>
struct Alpha
{ static void f () { /* do something */ } };
your f() can call a variadic f_helper()
void f (std::vector<typeEnum> const & eVec)
{ f_helper<>(eVec, 0u); }
realized as follows
template <typeEnum ...>
void f_helper (std::vector<typeEnum> const &, ...)
{ }
template <typeEnum ... Tes>
typename std::enable_if<(sizeof...(Tes) < 6u)>::type
f_helper (std::vector<typeEnum> const & eVec, std::size_t index)
{
if ( index < eVec.size() )
switch ( eVec[index++] )
{
case A: f_helper<Tes..., A>(eVec, index); break;
case B: f_helper<Tes..., B>(eVec, index); break;
case C: f_helper<Tes..., C>(eVec, index); break;
}
else
Alpha<Tes...>::f();
}
Observe that I've posed a very low limit (5, sizeof...(Tes) < 6u) to the length of the variadic list because the number of developed Alpha grows exponentially.
Also observe that I've added a do-nothing version of f_helper(); it's necessary because the less-than-6-length recursively call f_helper(), can call it with a variadic list of 6 enums that must be managed in some way.
The following is a full compiling example
#include <vector>
enum typeEnum { A, B, C };
template <typeEnum ...>
struct Alpha
{ static void f () { } };
template <typeEnum ...>
void f_helper (std::vector<typeEnum> const &, ...)
{ }
template <typeEnum ... Tes>
typename std::enable_if<(sizeof...(Tes) < 6u)>::type
f_helper (std::vector<typeEnum> const & eVec, std::size_t index)
{
if ( index < eVec.size() )
switch ( eVec[index++] )
{
case A: f_helper<Tes..., A>(eVec, index); break;
case B: f_helper<Tes..., B>(eVec, index); break;
case C: f_helper<Tes..., C>(eVec, index); break;
}
else
Alpha<Tes...>::f();
}
void f (std::vector<typeEnum> const & eVec)
{ f_helper<>(eVec, 0u); }
int main ()
{
f({A, B, C, A});
}
If you want specific functions from runtime variable then use a map instead. Template is the wrong tool for the job as you have to write lot just to transform variable into constants.
Assuming that you enum have a default value None and that you have up to say 5 arguments, you can define a map like this:
enum MyEnum { None = 0, A, B, C, D... };
using MyKey = std::tuple<MyEnum, MyEnum, MyEnum, MyEnum, MyEnum>;
using MyFunction = std::function<void()>;
Then you have somewhere a map of function (a singleton)
std::map<MyKey, MyFunction> myMap;
A utility function could be helpful to create a key from a variable number of arguments:
MyKey MakeKey(MyEnum e1, MyEnum e2 = None, MyEnum e3 = None, MyEnum e4 = None, MyEnum e5 = None)
{
return std::make_tuple(e1, e2, e3, e4, e5);
}
myMap.emplace(MakeKey(A, B), [](){ /* some code */ });
MyEnum AtOrDefault(const vector<enum> &eVec, int index)
{
return index < eVec.size() ? eVec[index] : None;
}
Then assuming you want to call the appropriate function from a vector, you could do:
void f(const vector<enum> &eVec)
{
if (eVec.size() > 5) throw some_exception;
MyKey key = std::make_typle(
AtOrDefault(eVec, 0),
AtOrDefault(eVec, 1),
AtOrDefault(eVec, 2),
AtOrDefault(eVec, 3),
AtOrDefault(eVec, 4));
auto &fn = myMap[key];
fn();
}
You could also use the idea of calculating a value assuming that you know the maximum number of elements in the enum. You could then create a CombinedEnumType:
enum CombinedEnumType : uint32_t { };
And defined a function
CombinedEnumType MakeCombinedEnumType(MyEnum e1, … MyEnum e5 = None)
{
const int MyEnumEcount = 5;
MyEnum a[] = { e1, e2, e3, e4, e5 };
uint32_t result = 0;
for (auto & item : a) { result *= MyEnumEcount; result += item; }
return static_cast<CombinedEnumType>(result);
}
This code is just for ideas. In real production code, you have to use constants, proper variable names, validate that a function exist for a given combination…
Answering my own question. I've realized that this approach won't work. Because when we write something like
Alpha<eVec[0]>::f()
Compiler throws an error - " error: expression must have a constant value"
So the only alternative left is
if(eVec.size() == 1){
switch(eVec[0]){
case A:
Alpha<A>::f()
.....
This is because the compiler needs to know all possible parameter types using which templates would be called during compile time.
I came across these lines of code:
template< int I > struct arg
{
arg()
{
}
template< class T > arg( T const & /* t */ )
{
// static assert I == is_placeholder<T>::value
typedef char T_must_be_placeholder[ I == is_placeholder<T>::value? 1: -1 ];
}
};
template< class T > struct is_placeholder
{
enum _vt { value = 0 };
};
What could be the reason the struct is_placeholder is templated while typename T is not used anywhere inside?
Why T_must_be_placeholder is defined in such a way so that it can have invalid size -1. To realise this, I called arg<1>(1) and it gave error: size of array is negative as expected. Is it some sort of sanity-check technique? Why doesn't the compiler report this issue if the arg<1>(1) call is not made?
While
int i = 0;
char a[i == 1 ? 1 : -1]; //No error
If sanity check works for 1st example, then how does it fail for second one?
is_placeholder is a template so that it can be specialized for different T. Say I create a struct example and want is_placeholder<example>::value to be 42. I would do this:
struct example {};
template< class T > struct is_placeholder
{
enum _vt { value = 0 };
};
template<>
struct is_placeholder<example>
{
enum _vt { value = 42 };
};
template< int I > struct arg
{
arg()
{
}
template< class T > arg( T const & /* t */ )
{
// static assert I == is_placeholder<T>::value
typedef char T_must_be_placeholder[ I == is_placeholder<T>::value ? 1: -1 ];
}
};
void test()
{
auto x = arg<42>(example()); // compiles
auto y = arg<43>(example()); // assertion
return 0;
}
In this case T_must_be_placeholder checks if is_placeholder<example>::value (which we just specialized to be 42) is the same as I. So if I is 42 it compiles, but if I is anything else, it won't.
Attempting to create an array with negative size is a way of deliberately preventing the code from compiling, so yes, this is probably a sanity check (static assertion, as it says in the comment).
Let's say I have a set of flags and a class like this:
/// <summary>Options controlling a search for files.</summary>
enum class FindFilesOptions : unsigned char
{
LocalSearch = 0,
RecursiveSearch = 1,
IncludeDotDirectories = 2
};
class FindFiles : boost::noncopyable
{
/* omitted */
public:
FindFiles(std::wstring const& pattern, FindFilesOptions options);
/* omitted */
}
and I want a caller to be able to select more than one option:
FindFiles handle(Append(basicRootPath, L"*"),
FindFilesOptions::RecursiveSearch | FindFilesOptions::IncludeDotDirectories);
Is it possible to support this in a strongly-typed way with C++11 enum class, or do I have to revert to untyped enumerations?
(I know the caller could static_cast to the underlying type and static_cast back, but I don't want the caller to have to do that)
It is certainly possible to use enum classes for bitmaps. It is, unfortunately, a bit painful to do so: You need to define the necessary bit operations on your type. Below is an example how this could look like. It would be nice if the enum classes could derive from some other type which could live in a suitable namespace defining the necessary operator boilerplate code.
#include <iostream>
#include <type_traits>
enum class bitmap: unsigned char
{
a = 0x01,
b = 0x02,
c = 0x04
};
bitmap operator& (bitmap x, bitmap y)
{
typedef std::underlying_type<bitmap>::type uchar;
return bitmap(uchar(x) & uchar(y));
}
bitmap operator| (bitmap x, bitmap y)
{
typedef std::underlying_type<bitmap>::type uchar;
return bitmap(uchar(x) | uchar(y));
}
bitmap operator^ (bitmap x, bitmap y)
{
typedef std::underlying_type<bitmap>::type uchar;
return bitmap(uchar(x) ^ uchar(y));
}
bool test(bitmap x)
{
return std::underlying_type<bitmap>::type(x);
}
int main()
{
bitmap v = bitmap::a | bitmap::b;
if (test(v & bitmap::a)) {
std::cout << "a ";
}
if (test(v & bitmap::b)) {
std::cout << "b ";
}
if (test(v & bitmap::c)) {
std::cout << "c ";
}
std::cout << '\n';
}
Templates play well with enum class so you can define sets of operators that work on sets of similar enumeration types. The key is to use a traits template to specify what interface(s) each enumeration conforms/subscribes to.
As a start:
enum class mood_flag {
jumpy,
happy,
upset,
count // size of enumeration
};
template<>
struct enum_traits< mood_flag > {
static constexpr bool bit_index = true;
};
template< typename t >
struct flag_bits : std::bitset< static_cast< int >( t::count ) > {
flag_bits( t bit ) // implicit
{ this->set( static_cast< int >( bit ) ); }
// Should be explicit but I'm lazy to type:
flag_bits( typename flag_bits::bitset set )
: flag_bits::bitset( set ) {}
};
template< typename e >
typename std::enable_if< enum_traits< e >::bit_index,
flag_bits< e > >::type
operator | ( flag_bits< e > set, e next )
{ return set | flag_bits< e >( next ); }
template< typename e >
typename std::enable_if< enum_traits< e >::bit_index,
flag_bits< e > >::type
operator | ( e first, e next )
{ return flag_bits< e >( first ) | next; }
http://ideone.com/kJ271Z
GCC 4.9 reported that some implicit member functions were constexpr while I was getting this to compile, so the templates should probably be so as well.
This should probably also have a free function to_scalar or something which returns an unsigned integer type given either an individual flag or a flag_bits set.
How about defining FindFiles so that it takes std::initializer_list of FindFilesOptions.
void FindFiles(std::wstring const& pattern, std::initializer_list<FindFilesOptions> options)
{
auto has_option = [&](FindFilesOptions const option)
{
return std::find(std::begin(options), std::end(options), option) != std::end(options);
};
if (has_option(FindFilesOptions::LocalSearch))
{
// ...
}
if (has_option(FindFilesOptions::RecursiveSearch))
{
// ...
}
if (has_option(FindFilesOptions::IncludeDotDirectories))
{
// ...
}
}
Then you could call it like so:
FindFiles({}, {FindFilesOptions::RecursiveSearch, FindFilesOptions::IncludeDotDirectories});
The problem is not the explicit enum type but the class scope.
With C++11, enum as compile time constant loose a lot of interest compared to a bunch of constexpr when you need operate on the value ( bitwise operation, incrementation, etc)
If you don't care about performance, change your options to set<FindFilesOptions>!
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;