Getting all values from an enum - c++

I have classes in the style of Class1 (see code). An enum and a function to get all the values from the enum. The values (FOO_1, FOO_2 etc) differ from Class to Class as well as the number of values (sizeof(Foos)).
I call the function once to get the sizeof the enum, reserve memory and with the second call I want to get all the values to *pFoos (2,1,6 in the sample code).
Is there a better way then using an array with all the values in it (size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR })?
class Class1{
enum Foos{
FOO_1 = 2,
FOO_X = 1,
FOO_BAR = 6
}
};
Class1::GetFoos(size_t* pFoos, size_t* pSize)
{
size_t len = sizeof(Foos);
if (len > *pSize)
{ //Call function once to get the size
*pSize= len ;
return -1;
}
for(size_t i = 0; i< *pSize; i++)
{
//copy all enum values to pFoos
}
};

Disclaimer: shameless plug – I am the author.
Reflective enums are possible in C++. I wrote a header-only library that captures a bunch of "patterns" at compile time and gives you syntax like this:
ENUM(Class1, int, FOO_1 = 2, FOO_X = 1, FOO_BAR = 6)
size_t count = Class1::_size;
for (size_t index = 0; index < Class1::_size; ++index)
do_anything(Class1::_values()[index]);
What it does internally is use the macro to generate an array of the values that you have declared, kind of like in your question, and use a bunch of other tricks to allow you to use initializers naturally. It then provides iterators and other things on top of the array.
Here is a link: https://github.com/aantron/better-enums
EDIT – internals
Here is a pseudocode sketch of what it does internally. The reason I am only giving a "sketch" is because there are a bunch of issues to consider when doing this portably. I will touch on all the most important elements.
ENUM(Class1, int, FOO_1 = 2, FOO_X = 1, FOO_BAR = 6)
notionally expands to
struct Class1 {
enum _enumerated { FOO_1 = 2, FOO_X = 1, FOO_BAR = 6 };
// Fairly obvious methods for how to iterate over _values and
// _names go here. Iterators are simply pointers into _values
// and _names below.
static size_t _size = sizeof(_values) / sizeof(int);
int _value;
};
int _values[] = {(fix_t<Class1>)Class1::FOO_1 = 2,
(fix_t<Class1>)Class1::FOO_X = 1,
(fix_t<Class1>)Class1::FOO_BAR = 6};
const char *_names[] = {"FOO_1 = 2", "FOO_X = 1", "FOO_BAR = 6"};
This is done by using variadic macros and stringization. The methods that deal with strings treat not only \0, but also space and equals as terminators, which allows them to ignore the initializers in the stringized constants that you see in _names.
The type fix_t is necessary because having assignments inside an array initializer is not valid C++. What that type does is take on the value of the enum, then ignore the assignment by an overloaded assignment operator, and then return the original value. A sketch:
template <typename Enum>
struct fix_t {
Enum _value;
fix_t(Enum value) : _value(value) { }
const fix_t& operator =(int anything) const { return *this; }
operator Enum() const { return _value; }
};
This makes the _values array possible declare even in the presence of initializers.
Of course, these arrays need to be prefixed so that you can have more than one enum like this. They also need to have the same as "extern inline" linkage for functions, so that they are shared between multiple compilation units.

Until c++ will get reflection you will not get any data from your enum! Simply you can not get "all" values from an enum. A enum is simply a kind of namespace where some constants can be defined and may be enumerated automatically. Not more at all. You have no text representation, no count information, no value to text information!

Is there a better way then using an array with all the values in it (size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR })?
If you're tagging the question as C++ I advise you to give up with the C way of doing things, so the better way to do this in C++ is using a std::vector:
class Class1{
enum Foos{
FOO_1 = 2,
FOO_X = 1,
FOO_BAR = 6
};
public:
std::vector<int> GetFoos()
{
// return all enum values
return {FOO_1, FOO_X, FOO_BAR};
}
};
You can use it this way:
Class1 c1;
auto foos = c1.GetFoos();
std::cout << "I have " << c1.size() << " foos:\n";
for (const auto &foo : foos) std::cout << foo << '\n';
If you don't want to create the vector at runtime, you can create it once declaring it static:
class Alpha{
enum Alphas{
BETA = 0b101010,
GAMMA = 0x20,
EPSILON = 050
};
static const std::vector<int> m_alphas;
public:
const std::vector<int> &GetAlphas()
{
return m_alphas;
}
};
// https://isocpp.org/wiki/faq/ctors#explicit-define-static-data-mems
const std::vector<int> Alpha::m_alphas = {BETA, GAMMA, EPSILON};
Live demo
I know that is a burden to maintain but since there's no way to iterate the values of an enum, all the code that tries to iterate them is a burden as well.
Maybe in the following answer you can find something useful to iterate enums in a better way for your goals:
enum to string in modern C++ and future C++17.

Related

C++ vector member initialization

I am confused about the output in the following program about the vec in Test. Why it's a vector with size 100 instead of 1? I thought std::vector<T> var{a} is the same as std::vector<T> var = {a}.
#include <iostream>
#include <vector>
using namespace std;
struct Value {
int a;
int b;
};
class Test {
public:
std::vector<struct Value> vec{100};
};
class Test2 {
public:
std::vector<int> vec{100};
};
int main()
{
Test test;
std::cout << "test size: " << test.vec.size() << std::endl;
Test2 test2;
std::cout << "test2 size: " << test2.vec.size();
return 0;
}
Output:
test size: 100
test2 size: 1
std::vector has a constructor with a std::initializer_list<T> argument. When using an initializer list like {100} this constructor will always take priority, if it is applicable.
For a std::vector<int> the initializer {100} is compatible with std::initializer_list<int> so that constructor will be used. It will create a vector containing the collection {100} which is a single int with the value 100.
For std::vector<Value> the initializer {100} is NOT compatible with a std::initializer_list<Value> argument. Value has no converting constructor for turning an int to a Value so you cannot construct a std::initializer_list<Value> from {100}. You can verify that this conversion is not allowed with this example. The compiler will try to take a lower priority constructor instead, and will use the constructor which initializes 100 default constructed Value.
If you add a Value::Value(int) constructor or use {{100}} as the initializer for Test2 you will find that the std::vector<Value> will now only contain a single element. In both cases, the initializer list is convertible to std::initializer_list<Value> and that constructor will now be used.
As you discovered the meaning of {100}, changes for T == int.
To answer your question briefly:
The 100 in vector<Value>{100} cannot be interpreted as a Value and therefore the size constructor takes precedence.
If you insist, {100} can be interpreted as Value, so you may need an extra curly braces, vector<Value>{ {100} }.
See the illustration here: https://godbolt.org/z/xcMT1oc5z
My advice, avoiding further discussion on legalities, is the following:
To keep the meaning across types, initialize consistently parenthesis for size-initialization and brackets for element(s), which forces you to do this:
std::vector<int> vec = std::vector<int>(100);
And in general:
std::vector<T> vec = std::vector<T>(100);
In this case 100 is always the size.
This may not be a totally helpful answer, but I decided to put a breakpoint in the class declaration for vector in the STD library.
Answer
In the definition of a vector, there are 3 ways it handles the assignment.
A struct will provide a value-construction, where as an int will be assigned as a sized range construction.
It reads std::vector<struct> vect{100}; as building a vector of length 100, while std::vector<int> vect{100}; is acting similarly vect.insert(v.end(),100);
This is based on the type of object passed in for .
For information's sake, the final option is taking a given value, and assigning it to a number of spots. So if you had 100, "x", it would put "x" into your vector 100 times.
The Journey
What I learned from this is that there's a point where your vector takes a size_type input and a _Valty&& input (which I don't know what that is yet. Will be looking it up later) and provides a construction between 3 different args.
My best guess would be that your struct is filling in for 1-args path and acts as a length declaration, while int as a native type falls into the 2-args path and acts as a value assignment.
The sizeof(Value) may == 0, while the size of an int will be 1.
Edit: I guessed 1 and 2 (or _Count == 0, and Count == 1), however I was wrong about this. It's _Count == 0 and _Count == 2. Which was very interesting.
template <class... _Valty>
_CONSTEXPR20 void _Construct_n(_CRT_GUARDOVERFLOW const size_type _Count, _Valty&&... _Val) {
// Dispatches between the three sized constructions.
// 1-arg -> value-construction, e.g. vector(5)
// 2-arg -> fill, e.g. vector(5, "meow")
// 3-arg -> sized range construction, e.g. vector{"Hello", "Fluffy", "World"}
auto& _Al = _Getal(); //////////////// For test1, _Count is 100, for test2, _Count is 1;
auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al);
auto& _My_data = _Mypair._Myval2;
_Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data);
if (_Count != 0) {
_Buy_nonzero(_Count);
_Tidy_guard<vector> _Guard{this};
// This one happens with a struct
if constexpr (sizeof...(_Val) == 0) {
_My_data._Mylast = _Uninitialized_value_construct_n(_My_data._Myfirst, _Count, _Al);
} else
if constexpr (sizeof...(_Val) == 1) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_Valty..., const _Ty&>);
_My_data._Mylast = _Uninitialized_fill_n(_My_data._Myfirst, _Count, _Val..., _Al);
} else
// This one happens with an int
if constexpr (sizeof...(_Val) == 2) {
_My_data._Mylast = _Uninitialized_copy(_STD forward<_Valty>(_Val)..., _My_data._Myfirst, _Al);
} else {
static_assert(_Always_false<_Ty>, "Should be unreachable");
}
_Guard._Target = nullptr;
}
_Proxy._Release();
}
What's really interesting as that it appears to be happening when the Allocator reference is assigned. I'm by no means an expert in the language, but I really wanted to figure this puzzle one! Thanks for the interesting challenge!
If you've never walked through a class definition before, I would recommend trying it out.

GTEST: False negative for incorrect number of macro arguments

I have a class A for which I've overloaded the operator[] such that if object a of class A can have an std::valarray passed to it in the following manner:
std::valarray<int> in{2,1};
auto b = a[in]; // lets say this returns an int k = 2
auto c = a[{2,1}]; // also returns an int k = 2
However, when using the GTEST framework, it doesn't like the a[{2,1}] notation, and complains that macro "EXPECT_EQ" passed 3 arguments, but takes just 2 if we are to try a test such as EXPECT_EQ(2, a[{2,1}]);
Surely a[{2,1}] is a single argument, since it evaluates to an int? This doesn't seem to be the case. A typical EXPECT_EQ such as EXPECT_EQ(2, 2); is just fine.
Below, I have a MWE of a class that overloads [] to takes a parameter of type std::valarray.
class A
{
private:
std::vector<int> elems;
public:
A(std::vector<int> elems)
: elems(elems){};
int operator[](std::valarray<int> idx) const
{
return get_elem(idx[0]);
}; // getter
int get_elem(int idx) const {return this->elems[idx];}; //getter
int &get_elem(int idx) {return this->elems[idx];}; //setter
};
int main()
{
std::vector<int> elems = {2, 5, 0, 9,
5, 1, 4, 6};
A a(elems);
std::cout<< "hello world" << std::endl;
std::valarray<int> in{2,1};
auto b = a[in]; // lets say this returns an int k = 2
auto c = a[{2,1}]; // also returns an int k = 2
std::cout<< b << std::endl;
std::cout<< c << std::endl;
return 0;
}
Given that my main() displays correct behaviour, I suspect that there is an issue with GTEST, or is evaluation order in C++ different from what I expect?
Since macros are involved, and there is no getting rid of them, the quickest solution is a judicious use of parentheses:
EXPECT_EQ(2, ( a[{2,1}] ));
The extra pair will prevent the comma from being interpreted as an argument separator for the macro. As for the comparison itself, a parenthesized expression has the exact same value and value-category as the expression withing the parentheses. So everything should still work1.
1 - Unless Google Test applies decltype to that second sequence of tokens, then the extra parentheses can potentially cause surprises. But it shouldn't be doing that.

create an array with just 2 bit for each cell in C++

I want create an array that each cell of it just have 2 bit in C++. is there any way to do this?
there is some method for creating bit array, but they allot just one bit to each cell.
If you want to write this from scratch:
The basic idea that probably all bit-set implementations use is to have an int[] (or really any other integral type), and to use bit-wise operations to get or set specific bits.
I'm sure you can find plenty of open-source implementations online, one example is Java's BitSet (available here). You can probably find C++'s bitset somewhere as well.
The same idea would apply here - just rather than mapping some index to one bit, it would be mapped to two bits instead.
If you can use standard library classes:
Here's something I quickly put together.
I wrote a twoBitSet class that extends std::bitset, which is essentially an array of bits; it then maps some supplied index to two bits in the bitset.
There's also a twoBit helper class - modifying the data using the [] operator without it is somewhat difficult.
#include <iostream>
#include <bitset>
template <size_t N>
class twoBit
{
typedef typename std::bitset<2*N>::reference bitRef;
bitRef a, b;
public:
twoBit(bitRef a1, bitRef b1): a(a1), b(b1) {};
const twoBit &operator=(int i) { a = i%2; b = i/2; return *this; };
operator int() { return 2*b + a; };
};
template <size_t N>
class twoBitSet : private std::bitset<2*N>
{
typedef typename std::bitset<2*N>::reference bitRef;
public:
twoBit<N> operator[](int index)
{
bitRef b1 = std::bitset<2*N>::operator[](2*index);
bitRef b2 = std::bitset<2*N>::operator[](2*index + 1);
return twoBit<N>(b1, b2);
};
};
int main()
{
twoBitSet<32> bs;
bs[0] = 2;
bs[1] = 3;
bs[2] = 1;
bs[3] = 0;
std::cout << bs[0] << std::endl; // prints 2
std::cout << bs[1] << std::endl; // prints 3
std::cout << bs[2] << std::endl; // prints 1
std::cout << bs[3] << std::endl; // prints 0
}
It's obviously fairly basic at the moment, it only allows the [] operator to be used and doesn't have any range checking.
Perhaps creating 2 [] operator functions (similar to bitset) would've been better - one just being an accessor, and one returning the twoBit object.
Live demo.
How about create a struct containing a 2 bit variable and a 6 bit one:
struct split
{
uint8_t sixbits : 6;
uint8_t twobits : 2;
}
then create a array of structs for that and only use the two bit part of the struct?
NB: Not tested... Got info from here.
std::vector<bool> has specialization you are looking for. You could then simply consider two consecutive array elements as one element of 2 bools or write up wrapper class for this if you are uncomfortable increment your index by 2 in loops. The problem with creating class with 2-bit variable is that it will still take up 8bits (1byte) as smallest variable size in C++ is 1byte.
Totally custom solution would be to create array of chars (8bit) and then use shift operator to use all bits of each char. This would however be needlessly complex as you would then need to unshift them each time you were accessing the values (...and that's exactly how std::vector<bool> specialization works).

strongly enum to integer and vice-versa

Here is my source (as answer) , how to implement underlying_value, and to_enum functions.
How to automatically convert strongly typed enum into int?
underlying_value - no problem.
but, to_enum - has problem.
see:
enum class E{ a = 1, b = 3, c = 5 };
auto e_a = utils::underlying_value(E::a); //OK
E t = utils::to_enum<E>( 2 ) ; // compiled, but it's incorrect. I think here must throws exception?
Q: how to implement to_enum correctly?
Despite the comments on the question, this can be done in C++11, though to do it without code repetition you will eventually have to wrap the enum class declaration in a macro. That may make my answer unsuitable, depending on your needs. Either way, doing the checked conversion requires some machinery, so I will get to the macro last.
The basic idea is to use constexpr functions to scan an array:
#include <iostream>
#include <stdexcept>
enum class E { a = 1, b = 3, c = 5 };
constexpr E values[] = {E::a, E::b, E::c};
constexpr size_t count = sizeof(values) / sizeof(E);
constexpr E to_enum(int value, size_t index = 0)
{
return
index >= count ? throw std::runtime_error("invalid integer") :
static_cast<int>(values[index]) == value ? values[index] :
to_enum(value, index + 1);
}
constexpr E converted = to_enum(3);
// Will not compile if uncommented.
// constexpr E bad_converted = to_enum(2);
int main()
{
std::cout << static_cast<int>(converted) << std::endl;
return 0;
}
This prints 3. If the line with bad_converted is uncommented, this code will not compile at all, as it says. The checked conversion can be done either at runtime or during compilation. It will be done during compilation if the argument to to_enum is a compile-time constant. Also, as you can probably see, this does a linear scan of values, but that can be replaced with another algorithm if it becomes a performance problem for a very large enum.
The code I just showed is a sketch that shows the underlying method. In order to make this less of a pain to use, you should wrap the declaration of E in a macro that will automatically generate the values[] array and the associated functions. I will show and rationalize the contents of this macro one point at a time.
The basic macro looks like this
// Declaration header
#define ENUM_CLASS(TypeName, __VA_ARGS__)
// Use
ENUM_CLASS(E, a = 1, b = 3, c = 5);
So, in this example, __VA_ARGS__ will be the tokens a = 1, b = 3, c = 5. So, we can declare the enum itself inside the macro as follows:
enum class TypeName { __VA_ARGS__ };
However, we cannot simply declare:
constexpr TypeName values[] = { __VA_ARGS__ };
because that expands to
constexpr TypeName values[] = { a = 1, b = 3, c = 5 };
which is not scoped (missing TypeName:: in front of each value), and is not valid C++ because of the extra assignment operators inside the array initializer. I will solve the second problem first. You need to define a class like this one:
template <typename E>
class swallow_assignment {
public:
E _value;
constexpr explicit swallow_assignment(E value) : _value(value)
{
}
template <typename Any>
constexpr const swallow_assignment& operator =(Any other) const
{
return *this;
}
constexpr operator E() const
{
return _value;
}
};
Now, you can write (swallow_assignment<E>)E::a = 1. What will happen is, at compile time, E::a will get converted to the assignable value (swallow_assignment<E>)E::a, which has the same internal representation as E::a. That value will then ignore the assignment of 1, and then will be converted back to E::a.
What's left is to prefix each of the declared constants so that we get
constexpr TypeName values[] =
{(swallow_assignment<E>)E::a = 1,
(swallow_assignment<E>)E::b = 3,
(swallow_assignment<E>)E::c = 5})
which will now be a valid initializer. This can be done with a mapping macro. I won't go into the details here, because that is a whole separate topic, but such a macro can be found here https://github.com/aantron/better-enums/blob/e28177b11a9e3d7152c5216d84fdf8939aff0eba/enum_preprocessor_map.h. Boost might also have a better one. Whatever macro you are using, I will assume that its signature is PP_MAP(prefix, __VA_ARGS__). The sketch for the final macro definition for the whole enum then becomes:
#define ENUM_CLASS(TypeName, __VA_ARGS__) \
enum class TypeName { __VA_ARGS__ }; \
constexpr TypeName values[] = \
{ PP_MAP((swallow_assignment<TypeName>)TypeName::, \
__VA_ARGS__) }; \
constexpr size_t count = sizeof(values) / sizeof(TypeName);
You will probably want to stuff these definitions into a specialization of a traits type, so that you can use this macro with more than one enum class (otherwise the arrays named values will collide). You may have to use weak symbols to avoid linking problems if you make values a static member of a traits class, however.
These last points are left as an exercise, because this answer is already way too long :) I have a library which does all of the above, though it wraps an enum instead of providing a traits specialization for an enum class. There is an unpublished branch with a combination of enum class/traits, however. You can see the library here: http://aantron.github.io/better-enums. The library's ::_from_integral() method corresponds to the to_enum function in your question, and it does both run-time and compile-time conversions.

defining an unusual 2-D array in C++

I want to reference the 1st Dimension of a 2 Dimensional array using an enum. However, the configurations that each enum value represents sometimes overlap (not in any patterned way), meaning the data in the array will sometimes be the same. I therefore would like to have some elements point to the same array of data, as in the diagram below.
Is there any way of doing this at declaration-time in C++?
Yes, you can build an array like that using an array of pointers; you will be able to reference elements in that array as if it were a regular 2D array. Here is an example:
enum MyEnum {
enumFirst = 0
, enumSecond = 1
, enumSecondShared = 2
, enumThird = 3
};
static int enumFirstData[] = {1, 2, 3};
static int enumSecondData[] = {4, 3, 2};
static int enumThirdData[] = {9, 7, 8};
int *enumData[] = {
enumFirstData
, enumSecondData
, enumSecondData // <== Shared
, enumSecondData
};
Now you can reference elements of this array like this:
for (int i = 0 ; i != 3 ; i++) {
cout << enumData[enumSecondShared][i] << endl;
}
Since you are using C++, using std::vector or std::array is a preferred way of making collections. You can use the same trick as above to establish shared collection elements.
you can define your own container type and use switch/case to map from the enums to the references. that way, you map those enums at declaration time, can use arbitrary enum values, and are more type safe than indexing an array of pointers.
it would look somehow like this (not tested), which specializes the std::map class:
template<class V>
class map<myenum,V>{
V r1,r2,r3;
public:
inline map(){}
inline r1& operator[](myenum e){
switch(e)
{
case E1: return r1;
case E2:
case E3: return r2;
case E4:
case E5: return r3;
}
}
}
map<myenum,vector<int>> example;
(sorry for not writing high-quality std-template style definitions, i'm not that used to program in c++ anymore.)
All you need is just std::map<your_enum_t, data_t*>
You should feel mapping according to your needs