Generic way to cast int to enum in C++ - c++

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

Related

Get byte representation of C++ class

I have objects that I need to hash with SHA256. The object has several fields as follows:
class Foo {
// some methods
protected:
std::array<32,int> x;
char y[32];
long z;
}
Is there a way I can directly access the bytes representing the 3 member variables in memory as I would a struct ? These hashes need to be computed as quickly as possible so I want to avoid malloc'ing a new set of bytes and copying to a heap allocated array. Or is the answer to simply embed a struct within the class?
It is critical that I get the exact binary representation of these variables so that the SHA256 comes out exactly the same given that the 3 variables are equal (so I can't have any extra padding bytes etc included going into the hash function)
Most Hash classes are able to take multiple regions before returning the hash, e.g. as in:
class Hash {
public:
void update(const void *data, size_t size) = 0;
std::vector<uint8_t> digest() = 0;
}
So your hash method could look like this:
std::vector<uint8_t> Foo::hash(Hash *hash) const {
hash->update(&x, sizeof(x));
hash->update(&y, sizeof(y));
hash->update(&z, sizeof(z));
return hash->digest();
}
You can solve this by making an iterator that knows the layout of your member variables. Make Foo::begin() and Foo::end() functions and you can even take advantage of range-based for loops.
If you can increment it and dereference it, you can use it any other place you're able to use a LegacyForwardIterator.
Add in comparison functions to get access to the common it = X.begin(); it != X.end(); ++it idiom.
Some downsides include: ugly library code, poor maintainability, and (in this current form) no regard for endianess.
The solution to the latter downside is left as an exercise to the reader.
#include <array>
#include <iostream>
class Foo {
friend class FooByteIter;
public:
FooByteIter begin() const;
FooByteIter end() const;
Foo(const std::array<int, 2>& x, const char (&y)[2], long z)
: x_{x}
, y_{y[0], y[1]}
, z_{z}
{}
protected:
std::array<int, 2> x_;
char y_[2];
long z_;
};
class FooByteIter {
public:
FooByteIter(const Foo& foo)
: ptr_{reinterpret_cast<const char*>(&(foo.x_))}
, x_end_{reinterpret_cast<const char*>(&(foo.x_)) + sizeof(foo.x_)}
, y_begin_{reinterpret_cast<const char*>(&(foo.y_))}
, y_end_{reinterpret_cast<const char*>(&(foo.y_)) + sizeof(foo.y_)}
, z_begin_{reinterpret_cast<const char*>(&(foo.z_))}
{}
static FooByteIter end(const Foo& foo) {
FooByteIter fbi{foo};
fbi.ptr_ = reinterpret_cast<const char*>(&foo.z_) + sizeof(foo.z_);
return fbi;
}
bool operator==(const FooByteIter& other) const { return ptr_ == other.ptr_; }
bool operator!=(const FooByteIter& other) const { return ! (*this == other); }
FooByteIter& operator++() {
ptr_++;
if (ptr_ == x_end_) {
ptr_ = y_begin_;
}
else if (ptr_ == y_end_) {
ptr_ = z_begin_;
}
return *this;
}
FooByteIter operator++(int) {
FooByteIter pre = *this;
(*this)++;
return pre;
}
char operator*() const {
return *ptr_;
}
private:
const char* ptr_;
const char* const x_end_;
const char* const y_begin_;
const char* const y_end_;
const char* const z_begin_;
};
FooByteIter Foo::begin() const {
return FooByteIter(*this);
}
FooByteIter Foo::end() const {
return FooByteIter::end(*this);
}
template <typename InputIt>
char checksum(InputIt first, InputIt last) {
char check = 0;
while (first != last) {
check += (*first);
++first;
}
return check;
}
int main() {
Foo f{{1, 2}, {3, 4}, 5};
for (const auto b : f) {
std::cout << (int)b << ' ';
}
std::cout << std::endl;
std::cout << "Checksum is: " << (int)checksum(f.begin(), f.end()) << std::endl;
}
You can generalize this further by making serialization functions for all data types you might care about, allowing serialization of classes that aren't plain-old-data types.
Warning
This code assumes that the underlying types being serialized have no internal padding, themselves. This answer works for this datatype because it is made of types which themselves do not pad. To make this work for datatypes that have datatypes that have padding, this method would need to be recursed all the way down.
Just cast a pointer to object to a pointer to char. You can iterate through the bytes by increment. Use sizeof(foo) to check overflow.
As long as you're able to make your class an aggregate, i.e. std::is_aggregate_v<T> == true, you can actually sort-of reflect the members of the structure.
This allows you to easily hash the members without actually having to name them. (also you don't have to remember updating your hash function every time you add a new member)
Step 1: Getting the number of members inside the aggregate
First we need to know how many members a given aggregate type has.
We can check this by (ab-)using aggregate initialization.
Example:
Given struct Foo { int i; int j; };:
Foo a{}; // ok
Foo b{{}}; // ok
Foo c{{}, {}}; // ok
Foo d{{}, {}, {}}; // error: too many initializers for 'Foo'
We can use this to get the number of members inside the struct, by trying to add more initializers until we get an error:
template<class T>
concept aggregate = std::is_aggregate_v<T>;
struct any_type {
template<class T>
operator T() {}
};
template<aggregate T>
consteval std::size_t count_members(auto ...members) {
if constexpr (requires { T{ {members}... }; } == false)
return sizeof...(members) - 1;
else
return count_members<T>(members..., any_type{});
}
Notice that i used {members}... instead of members....
This is because of arrays - a structure like struct Bar{int i[2];}; could be initialized with 2 elements, e.g. Bar b{1, 2}, so our function would have returned 2 for Bar if we had used members....
Step 2: Extracting the members
Now that we know how many members our structure has, we can use structured bindings to extract them.
Unfortunately there is no way in the current standard to create a structured binding expression with a variable amount of expressions, so we have to add a few extra lines of code for each additional member we want to support.
For this example i've only added a max of 4 members, but you can add as many as you like / need:
template<aggregate T>
constexpr auto tie_struct(T const& data) {
constexpr std::size_t fieldCount = count_members<T>();
if constexpr(fieldCount == 0) {
return std::tie();
} else if constexpr (fieldCount == 1) {
auto const& [m1] = data;
return std::tie(m1);
} else if constexpr (fieldCount == 2) {
auto const& [m1, m2] = data;
return std::tie(m1, m2);
} else if constexpr (fieldCount == 3) {
auto const& [m1, m2, m3] = data;
return std::tie(m1, m2, m3);
} else if constexpr (fieldCount == 4) {
auto const& [m1, m2, m3, m4] = data;
return std::tie(m1, m2, m3, m4);
} else {
static_assert(fieldCount!=fieldCount, "Too many fields for tie_struct! add more if statements!");
}
}
The fieldCount!=fieldCount in the static_assert is intentional, this prevents the compiler from evaluating it prematurely (it only complains if the else case is actually hit)
Now we have a function that can give us references to each member of an arbitrary aggregate.
Example:
struct Foo {int i; float j; std::string s; };
Foo f{1, 2, "miau"};
// tup is of type std::tuple<int const&, float const&, std::string const&>
auto tup = tie_struct(f);
// this will output "12miau"
std::cout << std::get<0>(tup) << std::get<1>(tup) << std::get<2>(tup) << std::endl;
Step 3: hashing the members
Now that we can convert any aggregate into a tuple of its members, hashing it shouldn't be a big problem.
You can basically hash the individual types like you want and then combine the individual hashes:
// for merging two hash values
std::size_t hash_combine(std::size_t h1, std::size_t h2)
{
return (h2 + 0x9e3779b9 + (h1<<6) + (h1>>2)) ^ h1;
}
// Handling primitives
template <class T, class = void>
struct is_std_hashable : std::false_type { };
template <class T>
struct is_std_hashable<T, std::void_t<decltype(std::declval<std::hash<T>>()(std::declval<T>()))>> : std::true_type { };
template <class T>
concept std_hashable = is_std_hashable<T>::value;
template<std_hashable T>
std::size_t hash(T value) {
return std::hash<T>{}(value);
}
// Handling tuples
template<class... Members>
std::size_t hash(std::tuple<Members...> const& tuple) {
return std::apply([](auto const&... members) {
std::size_t result = 0;
((result = hash_combine(result, hash(members))), ...);
return result;
}, tuple);
}
template<class T, std::size_t I>
using Arr = T[I];
// Handling arrays
template<class T, std::size_t I>
std::size_t hash(Arr<T, I> const& arr) {
std::size_t result = 0;
for(T const& elem : arr) {
std::size_t h = hash(elem);
result = hash_combine(result, h);
}
return result;
};
// Handling structs
template<aggregate T>
std::size_t hash(T const& agg) {
return hash(tie_struct(agg));
}
This allows you to hash basically any aggregate struct, even with arrays and nested structs:
struct Foo{ int i; double d; std::string s; };
struct Bar { Foo k[10]; float f; };
std::cout << hash(Foo{1, 1.2f, "miau"}) << std::endl;
std::cout << hash(Bar{}) << std::endl;
full example on godbolt
Footnotes
This only works with aggregates
No need to worry about padding because we access the members directly.
You have to add a few more ifs into tie_struct if you need more than 4 members
The provided hash() function doesn't handle all types - if you need e.g. std::array, std::pair, etc... you need to add overloads for those.
It's a lot of boilerplate code, but it's insanely powerful.
You can also use Boost.PFR for the aggregate-to-tuple part, if you are allowed to use boost

Data controlled programs in c++

Not to sure how to name this question because the problem itself is looking for a construct of which I don´t know its name.
The problem is I am dealing with programs whose control flow depends greatly of data.
For example I created a MIPS simulator which implemented a list of more than 50 instructions, each implemented on its own and everything governed by a huge switch case
switch (function){ //Function is an int, each function (eg SLL) is
case 0: //associated with one
if (state->debug_level > 0){
fprintf(state->debug_out, "SLL\n");
}
step_err = SLL(state, rs, rt, rd, sa);
break;
case 2:
if (state->debug_level > 0){
fprintf(state->debug_out, "SRL\n");
}
step_err = SRL(state, rs, rt, rd, sa);
break;
case 3:
if (state->debug_level > 0){
fprintf(state->debug_out, "SRA\n");
}
//
I have been told that this could have been implemented using function pointers, but to do so what I am looking for is a way of relating data of any kind, say a string to other data, say an integer. I am aware of maps but wouldn't want to push back each pair. I am looking for some sort of array like syntax I think if seen before which might look something similar to this:
¿type? function_codes[]{
0, "SLL";
2, "SRL";
3, "SRA";
...
}
I am not looking for a solution to this problem but a generic approach to introducing quick relationships between data and using this to modify control flow.
EDIT AFTER ANSWERS
What I was actually looking for but I didnt know was indeed maps but in particular its initialization syntax similar to an array (see accepted answer). This used with function pointers did the required job.
As you guessed, function pointers are in fact a good way to do this. Since you specify that you don't want to use a Map, this is how you would implement your integer-based function dispatch using an array of function pointers. Note that since I don't know the type signature of your MIPS functions (SLL, SRL, etc.) I've used dummy placeholder type names.
typedef ret_t (*mips_func)(arg1_t, arg2_t, arg3_t, arg4_t, arg5_t);
mips_func function_codes[] = {
&SLL,
&SRL,
&SRA,
...
};
//...Later, in the part of your code that used to contain the big switch statement
step_err = (*function_codes[function])(state, rs, rt, rd, sa);
The syntax &SLL gets a pointer to the function SLL, which I assume is already in scope because you can call it directly from your switch statement.
Note that this assumes the numeric codes for the functions are a continuous sequence of integers from 0 to [max code value]. If some numeric codes are unused, then you will either need to leave explicit gaps in your array (by placing a NULL pointer in one or more entries) or use std::map<int, mips_func> so that you can use arbitrary non-continuous integer values as keys to functions. Fortunately, using a Map still doesn't require push_backing each element, since C++ now has initializer lists. The same code using a Map would look like this:
typedef ret_t (*mips_func)(arg1_t, arg2_t, arg3_t, arg4_t, arg5_t);
std::map<int, mips_func> function_codes = {
{0, &SLL},
{2, &SRL},
{4, &SRA},
...
};
//Using the Map looks exactly the same, due to its overloaded operator[]
step_err = (*function_codes[function])(state, rs, rt, rd, sa);
For simplify you can use associative containers. If the order is important then use std::map, or std::unordered_map in the other case.
And you can use syntax similar to the desired
std::map<size_t, std::string> codes_map = decltype(codes_map) {
{ 0, "val1" },
{ 1, "val2" }
};
You could group the data as static members w/ the same name across structs, then use templates to access them generically:
struct A { auto call() const { return "((1))"; }; static const char * name; };
struct B { auto call() const { return "{{2}}"; }; static const char * name; };
struct C { auto call() const { return "<<3>>"; }; static const char * name; };
// n.b. these `T...` have: `sizeof(T) == ... == sizeof(empty_struct)`
const char * A::name = "A";
const char * B::name = "B";
const char * C::name = "C";
boost::variant (and the soon to be implemented std::variant) implements a type-safe union, which provides a very clean and efficient way of using these structs as values:
#include <cstdio>
#include <vector>
#include <boost/variant.hpp>
int main()
{
std::vector<boost::variant<A, B, C>> letters{A{}, B{}, C{}, B{}, A{}};
auto visitor = [](auto x) { std::printf("%s(): %s\n", x.name, x.call()); };
for (auto var : letters) { boost::apply_visitor(visitor, var); }
}
Demo
It seems like you have two problems: the flow-control issue (dispatch) and the map issue (an implementation note). I get that the program flow is nonstatic and unknowable at compile-time… but so is the map static? For static maps I get a lot of mileage out of using a traits-ish approach to create a compile-time mapping. Here’s a quick example mapping file suffixes to Objective-C enum constants:
namespace objc {
namespace image {
template <std::size_t N> inline
constexpr std::size_t static_strlen(char const (&)[N]) { return N; }
template <NSBitmapImageFileType t>
struct suffix_t;
#define DEFINE_SUFFIX(endstring, nstype) \
template <> \
struct suffix_t<nstype> { \
static constexpr std::size_t N = static_strlen(endstring); \
static constexpr char const str[N] = endstring; \
static constexpr NSBitmapImageFileType type = nstype; \
};
DEFINE_SUFFIX("tiff", NSTIFFFileType);
DEFINE_SUFFIX("bmp", NSBMPFileType);
DEFINE_SUFFIX("gif", NSGIFFileType);
DEFINE_SUFFIX("jpg", NSJPEGFileType);
DEFINE_SUFFIX("png", NSPNGFileType);
DEFINE_SUFFIX("jp2", NSJPEG2000FileType);
template <NSBitmapImageFileType nstype>
char const* suffix_value = suffix_t<nstype>::str;
}
}
… see how that works? the nice part is that using it has no runtime overhead, which if your map is static, you can use something like that.
For dynamic flow-control and dispatch, function pointers work; that is what happens automatically if you use polymorphic classes and virtual functions but it seems like you have an architecture in place already that may not be amenable to being redone with such high-modernist architectural notions. I like c++11 lambdas as they solve like 90% of my problems in this arena. Perhaps you can elablrate (I will amend my answer)!
If you only have a small number of indices to support, from 0 to 50, you'll get the best performance if you put your function pointers in an array and not a map.
The syntax is also short:
#include <iostream>
#include <functional>
static void f0() {
std::cout << "f0\n";
}
static void f1() {
std::cout << "f1\n";
}
void main()
{
std::function<void()> f[2] = { f0, f1 };
f[0](); // prints "f0"
f[1](); // prints "f1"
}
Or, if you prefer classes over functions:
#include "stdafx.h"
#include <iostream>
class myfunc {
public:
virtual void run() abstract;
virtual ~myfunc() {}
};
class f0 : public myfunc {
public:
virtual void run() {
std::cout << "f0\n";
}
};
class f1 : public myfunc {
public:
virtual void run() {
std::cout << "f1\n";
}
};
void main()
{
myfunc* f[2] = { new f0(), new f1() };
f[0]->run(); // prints "f0"
f[1]->run(); // prints "f1"
for (int i = 0; i < sizeof(f) / sizeof(f[0]); ++i)
delete f[i];
}
Given some definitions
#include <iostream>
#include <iterator>
#include <algorithm>
#include <stdexcept>
#include <map>
using namespace std;
struct state{
int debug_level = 1;
const char* debug_out = "%s";
} s;
// some functions to call
void SLL(state& s, int, int, int, int){
cout << "SLL";
}
void SLR(state& s, int, int, int, int){
cout << "SLR";
}
void SLT(state& s, int, int, int, int){
cout << "SLT";
}
You can use a Map
auto mappedname2fn = map<string, delctype(SLL)*>{
{"SLL", SLL},
{"SLR", SLR}
};
// call a map function
mappedname2fn["SLR"](s, 1, 2, 3, 4);
If you don't want a map you can use a pre-sorted array for a binary search
Here's a binary search of an array of name, function pairs
template<typename P, int N, typename ...T>
auto callFn(P(&a)[N], string val, T&&... params){
auto it = lower_bound(a, a+N, make_pair(val, nullptr),
[](auto& p1, auto& p2){return p1.first < p2.first;});
if(it==(a+N) || val<it->first) throw logic_error("not found");
return it->second(forward<T>(params)...);
}
So you can set up an array and use that:-
// array sorted in alphabetical order for binary search to work
pair<string, decltype(SLL)*> name2fn[] = {
{"SLL", SLL},
{"SLR", SLR},
{"SLT", SLT}
};
void callFn(string name, state& s, int a, int b, int c, int d){
try{
callFn(name2fn, name, s, a, b, c, d);
}
catch(exception& e){
cout << e.what();
}
}
// call it
callFn("SLL", s, 1, 2, 3, 4);

Visual C++ 2013 / v12 C++11 enum class C1001 compiler error

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?

Template Class to differentiate object type?

Can I use C++ template classes to differentiate object types? Or what should I use?
Eg. I have a class Synonym and it can be of type Statement, Procedure, etc for example. I have functions that accepts these synonyms and evaluates them depending on its type. So I was thinking it will be nice if I can do something like:
enum Types { Statement, Procedure, Variable, ... };
template <typename Types>
class Synonym { ... }
void evaluate(Synonym<Statement> s, Synonym<Variable> v) { do something }
^ so that I can do this ... instead of checking the type in function like:
void evaluate(Synonym s, Synonym v) {
assert(s.type == Statement);
assert(v.type == Variable);
// also would like to eliminate things like: (if possible)
switch(s.type) {
case XXX: doSomething ...
case YYY: doAnotherThing ...
}
}
You could create a function template and then specialize on that template
template<typename Type>
void evaluate (Type t) {}
template<>
void evaluate<Statement>( Statement s)
{}
This way, when you pass a Statement it will pick that overload, and you can do different behaviors depending on type.
I think using a variant and visitor pattern would be suited. Have a look at Boost.Variant here: http://www.boost.org/doc/libs/1_51_0/doc/html/variant.html, the last example (also below but expanded) shows a visitor implementation. There are also other variant and visitor implementations. std::any and loki are also options. I personally like loki but that is probably just because I'm a huge fan of Alexandrescu.
#include "boost/variant.hpp"
#include <iostream>
class ToLengthVisitor : public boost::static_visitor<int>
{
public:
int operator()(int i) const
{
return i;
}
int operator()(const std::string & str) const
{
return str.length();
}
int operator()(const char * str) const
{
const char * temp = str;
while(*temp != '\0') temp++;
return temp-str;
}
};
int main()
{
typedef boost::variant< int, std::string, const char * > MyVariant;
MyVariant u(std::string("hello world"));
std::cout << u; // output: hello world
MyVariant cu(boost::get<std::string>(u).c_str());
int result = boost::apply_visitor( ToLengthVisitor(), u );
std::cout << result; // output: 11 (i.e., length of "hello world")
result = boost::apply_visitor( ToLengthVisitor(), cu );
std::cout << result; // output: 11 (i.e., length of "hello world")
}

String to enum in C++

Is there a way to associate a string from a text file with an enum value?
The problem is: I have a few enum values stored as string in a text file which I read on the fly on meeting some condition... Now I want to assign the read value to an enum.
What is the most effective way to do so? It doesn't need to be the simplest approach.
You can set up a map that you can use over and over:
template <typename T>
class EnumParser
{
map <string, T> enumMap;
public:
EnumParser(){};
T ParseSomeEnum(const string &value)
{
map <string, T>::const_iterator iValue = enumMap.find(value);
if (iValue == enumMap.end())
throw runtime_error("");
return iValue->second;
}
};
enum SomeEnum
{
Value1,
Value2
};
EnumParser<SomeEnum>::EnumParser()
{
enumMap["Value1"] = Value1;
enumMap["Value2"] = Value2;
}
enum OtherEnum
{
Value3,
Value4
};
EnumParser<OtherEnum>::EnumParser()
{
enumMap["Value3"] = Value3;
enumMap["Value4"] = Value4;
}
int main()
{
EnumParser<SomeEnum> parser;
cout << parser.ParseSomeEnum("Value2");
}
std::map< string, enumType> enumResolver;
I agree with many of the answers that std::map is the easiest solution.
If you need something faster, you can use a hash map. Perhaps your compiler already offers one, such as hash_map or the upcoming standard unordered_map, or you can get one from boost. When all the strings are known ahead of time, perfect hashing can be used as well.
Accepted answer doesn't contain full listing. I'm adding EnumParser.h which I created from the accepted answer, hope it can help
#include <string>
#include <map>
using namespace std;
template <typename T> class EnumParser
{
map<string, T> enumMap;
public:
EnumParser(){};
T ParseSomeEnum(const string &value)
{
typename map <string, T>::const_iterator iValue = enumMap.find(value);
if (iValue == enumMap.end())
throw runtime_error("");
return iValue->second;
}
};
Usage is simple:
enum FieldType
{
Char,
Integer,
Long,
Fixed,
Price,
Date,
Time
};
EnumParser<FieldType>::EnumParser()
{
enumMap["Char"] = Char;
enumMap["Integer"] = Integer;
enumMap["Long"] = Long;
enumMap["Fixed"] = Fixed;
enumMap["Price"] = Price;
enumMap["Date"] = Date;
enumMap["Time"] = Time;
}
use:
EnumParser<FieldType> fieldTypeParser;
FieldType val = fieldTypeParser.ParseSomeEnum(stringValue)
Look at Boost.Bimap, it provides bidirectional associations between two sets of values.
You can also choose the underlying container.
Using a std::map raises the question: how does the map get initialised? I would rather use a function:
enum E { A, B };
E f( const std::string & s ) {
if ( s == "A" ) {
return A;
}
else if ( s == "B" ) {
return B;
}
else {
throw "Your exception here";
}
}
Is this what you want? The initialization is straight, and no instantiation is needed.
usage:
enum SomeEnum
{
ENUM_ONE,
ENUM_TWO,
ENUM_THREE,
ENUM_NULL
};
DEFINE_PAIRLIST(CEnumMap, SomeEnum)
INIT_PAIRLIST(CEnumMap)=
{
{"One", ENUM_ONE},
{"Two", ENUM_TWO},
{"Three", ENUM_THREE},
{"", ENUM_NULL}
};
main{
// Get enum from string
SomeEnum i = CEnumMap::findValue("One");
// Get string from enum
SomeEnum eee = ENUM_ONE;
const char* pstr = CEnumMap::findKey(eee);
...
}
library:
template <class T>
struct CStringPair
{
const char* _name;
T _value;
};
template <class T, class Derived>
struct CStringPairHandle
{
typedef CStringPair<T> CPair;
static const CStringPair<T> * getPairList(){
return Derived::implementation();
}
static T findValue(const char* name){
const CStringPair<T> * p = getPairList();
for (; p->_name[0]!=0; p++)
if (strcmp(name,p->_name)==0)
break;
return p->_value;
}
static const char* findKey(T value){
const CStringPair<T> * p = getPairList();
for (; p->_name[0]!=0; p++)
if (strcmp(value,p->_value)==0)
break;
return p->_name;
};
};
#define DEFINE_PAIRLIST(name, type) struct name:public CStringPairHandle<type, name>{ \
static CPair _pairList[]; \
static CPair* implementation(){ \
return _pairList; \
}};
#define INIT_PAIRLIST(name) name::CPair name::_pairList[]
Parse the string yourself, match the string with a value (which is also an index to a map<string, enum>.
You can calculate the hash of the string and then use this:
template <typename H, typename E>
E map_hash(H const key, std::initializer_list<std::pair<H, E>> const il)
{
auto const i(
std::find_if(il.begin(),
il.end(),
[key](auto& p)
{
return p.first == key;
}
)
);
assert(i != il.end());
return i->second;
}
Using C++ reflection library from here: https://github.com/tapika/cppreflect
You can - include library like this:
#include "cppreflect/cppreflect.h"
Basic usage:
Declare enumeration:
DECLARE_ENUM( enumName,
// Prefix for all enums, "" if no prefix used.
"myenum_",
myenum_enumValue1,
myenum_enumValue2,
myenum_enumValue3 = 5,
// comment
myenum_enumValue4
);
Conversion logic:
From enumeration to string:
printf( EnumToString(myenum_enumValue3).c_str() );
=> "enumValue3"
From string to enumeration:
enumName value;
if( !StringToEnum("enumValue4", value) )
printf("Conversion failed...");
=>
value == myenum_enumValue4
Main / core functionality resides in here:
https://github.com/tapika/cppreflect/blob/master/cppreflect/enumreflect.h