I am trying to use enumerations of std::vector<bool> because i'd like to represent some values as a vector of bits.
So I tried the following code:
enum class ProximityStateEnum : std::vector<bool> {
Unknown = std::vector<bool>{false,false},
NotConnected = std::vector<bool>{false,true},
Connected = std::vector<bool>{true,false},
ConnectedButNotLatched = std::vector<bool>{true,true}
};
But when I compile the code with this, I get the error underlying type ‘std::vector<bool>’ of ‘ProximityStateEnum’ must be an integral type. How can I do to create an enum of vectors ?
enum and enum class are not meant as aliases to instances of arbitrary objects - they're limited to integral types, and every explicit value must be a constant expression. See the cppreference page on enum for more information.
If you want to give a name to particular instances of std::vector<bool>, either use functions or inline variables:
auto Unknown() { return std::vector<bool>{false,false}; }
auto NotConnected() { return std::vector<bool>{false,true}; }
auto Connected() { return std::vector<bool>{true,false}; }
auto ConnectedButNotLatched() { return std::vector<bool>{true,true}; }
// ...or, in C++17:
inline auto Unknown = std::vector<bool>{false,false};
inline auto NotConnected = std::vector<bool>{false,true};
inline auto Connected = std::vector<bool>{true,false};
inline auto ConnectedButNotLatched = std::vector<bool>{true,true};
In your particular use case, you don't really need an std::vector because you know the size of your bitset in advance - std::bitset or binary literals will work well:
enum class ProximityStateEnum : /* some suitable type */
{
Unknown = 0b00,
NotConnected = 0b01,
Connected = 0b10,
ConnectedButNotLatched = 0b11
};
You cannot; enums can only be based on integral types.
If it can be helpful, since C++14 you can use binary literals to specify their values:
enum class ProximityStateEnum {
Unknown = 0b00,
NotConnected = 0b01,
Connected = 0b10,
ConnectedButNotLatched = 0b11
};
which is pretty much as clear as your idea, but way more compact and orders of magnitude more efficient than any hypothetical std::vector based solution.
Another possibility that is often used in enums where particular bits have particular meaning is to build them with expressions:
enum ProximityStateEnum {
Unknown = 0b00,
NotConnected = 0b01,
Connected = 0b10,
ConnectedButNotLatched = Connected | NotConnected
};
As said by other, enums can only be integral types.
If the lenght of your vectors of bool is constant (as in you example, where is 2), you can substitute the std::vector<bool> with a std::array<bool, length>. One advantage in using std::array instead of std::vector is that you can define it as constexpr.
So a reasonable (IMHO) alternative is define a enum type based on std::size_t, with sequential values starting from 0,
enum ProximityStateEnum : std::size_t
{
Unknown = 0U,
NotConnected,
Connected,
ConnectedButNotLatched
};
and a static constexpr std::array of std::arrays of bool
// .......................... last value of the enum vvvvvvvvvvvvvvvvvvvvvv
static constexpr std::array<std::array<bool, 2U>, 1U+ConnectedButNotLatched>
pseArr { { { {false, false} }, { {false, true} },
{ {true, false} }, { {true, true} } } };
that you can use as follows
pseArr[NotConnected][0]
Related
I have two enum's like as shown below:
typedef enum {
NONE = 0,
test1,
test2
} TestType;
enum class type
{
zero = 0,
one,
two,
three
};
When I am assigning one enum to another like as shown below:
const type f_eType;
TestType l_etestType = f_eType;
I am getting the below error:
a value of type "type" cannot be used to initialize an entity of type "TestType"
Could someone please help me how to resolve this error without using static_cast.
If you don't want to use static_cast then you'll have to define the conversion behaviour on your own:
TestType convert(type val) {
switch(val) {
case type::zero:
return NONE;
//...
}
}
TestType l_etestType = static_cast<TestType>(f_eType)
Following the C++ enum pattern I already described here, I was trying to do a similar thing but this time the sequence of values I want to use is not comprehended of continuous integer numbers.
The code is obviously wrong:
class Rotations
{
enum PossibleIndexes
{
ZERO,
PLUS180,
PLUS90,
MINUS90
};
enum PossibleValues
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
static int Count() { return MINUS90 + 1; }
static PossibleValues Default(){ return ZERO; }
};
as there will be conflicts between elements inherent of the two enums.
So my question is: What is the best approach to implement a fixed number of hardcoded Rotations{0, 180, 90, -90} which has also a Default and a Count functionality?
You can always keep a static std::initializer_list containing all possible values
namespace PossibleValues
{
enum Type
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
constexpr auto Values = {ZERO, PLUS180, PLUS90, MINUS90};
size_t Count() { return Values.size(); }
Type Default() { return *begin(Values); }
}
This approach will have the added bonus of being able to iterate of the values of the enum in a for-loop
Note: I wish the compiler could generate all that code though, at least for enum class
Disclaimer: I am mentioning an open-source library that I recently published.
You may want to look at Better Enums. It will save you from having to repeat anything.
#include <enum.h>
ENUM(Rotations, int, ZERO = 0, PLUS180 = 180, PLUS90 = 90, MINUS90 = -90)
You could then access the number of constants as
Rotations::_size
There is currently no built-in way of declaring a default value. However, the default constructor is currently private, so you would be forced to provide a value when creating a Rotations value. There is a syntactically "nice" way to do this shown here – look at how invalid is defined using a template. It might be complete overkill for your needs. If you try this library and have any feedback concerning default values, please let me know.
I should note that the count and default value are generated at compile time.
Due to the limitations of Visual C++ 2010 Compilation Toolkit (not fully C++11 compliant), I had to surrender myself to inferior approaches.
The post at https://stackoverflow.com/a/15961043/383779 also suggested me an interesting approach for getting the values.
class Rotations
{
public:
typedef enum
{
ZERO= 0,
PLUS180= 180,
PLUS90 = 90,
MINUS90 = -90
}PossibleValues;
static const PossibleValues PossibleValuesCollection(int index) {
static const PossibleValues values[] = { ZERO, PLUS180, PLUS90, MINUS90 };
return values[index];
}
static int Count() { return 4; }
static PossibleValues Default(){ return ZERO; }
};
I want to define a ICMP header as a pod type:
struct ICMPHeader
{
uint8_t Type; // ICMP type
uint8_t Code; // Subtype, value is dependent on ICMP type.
uint16_t Checksum; // Error checking data. See RFC 1071
uint32_t RestOfHeader; // Varies based on ICMP type and code.
};
For the ICMPType field I can use strongly typed enums to make it a bit nicer:
enum class ICMPType : uint8_t
{
EchoReply = 0,
Reserved1 = 1,
Reserved2 = 2,
DestinationUnreachable = 3,
SourceQuench = 4
// etc...
};
struct ICMPHeader
{
ICMPType Type; // ICMP type
uint8_t Code; // Subtype, value is dependent on ICMP type.
uint16_t Checksum; // Error checking data. See RFC 1071
uint32_t RestOfHeader; // Varies based on ICMP type and code.
};
Now, I naturally also want to specify the Code field as an enum. It would be nice if I could use template specialization syntax, but a quick test reveals that it doesn't work:
// Compiler error
template<ICMPType>
enum class ICMPCode;
template<>
enum class ICMPCode<ICMPType::DestinationUnreachable>
{
DestinationNetworkUnreachable = 0,
DestinationHostUnreachable = 1,
DestinationProtocolUnreachable = 2
};
One option would be to wrap them in structs:
// Meaning of ICMP code is dependent on ICMP type.
template<ICMPType>
struct ICMPCode;
// Subcodes for DestinationUnreachable
template<> struct ICMPCode<ICMPType::DestinationUnreachable>
{
enum class Code : uint8_t
{
DestinationNetworkUnreachable = 0,
DestinationHostUnreachable = 1,
DestinationProtocolUnreachable = 2
// etc...
};
};
// Access: ICMPCode<ICMPType::DestinationUnreachable>::Code::DestinationHostUnreachable
But doing it like this makes me feel that I'm just messing around and making things too complex..
I guess this is a specific example of a more general question: How to setup a system of types and subtypes? Any suggestions?
Ps:
See also: http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Header
Sample code:
#include <iostream>
// Trying to model ICMP types and codes with strongly typed enums
// See also http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Header
enum class ICMPType : uint8_t
{
EchoReply = 0,
Reserved1 = 1,
Reserved2 = 2,
DestinationUnreachable = 3,
SourceQuench = 4
// etc...
};
// Meaning of ICMP code is dependent on ICMP type.
template<ICMPType>
struct ICMPCode;
// Subcodes for DestinationUnreachable
template<> struct ICMPCode<ICMPType::DestinationUnreachable>
{
enum class Code : uint8_t
{
DestinationNetworkUnreachable = 0,
DestinationHostUnreachable = 1,
DestinationProtocolUnreachable = 2
// etc...
};
};
ICMPCode<ICMPType::DestinationUnreachable>::Code GetReasonWhyDestinationIsUnreachable()
{
return ICMPCode<ICMPType::DestinationUnreachable>::Code::DestinationHostUnreachable;
}
int main()
{
std::cout << static_cast<int>(GetReasonWhyDestinationIsUnreachable()) << std::endl;
}
I don't think you can do this statically at compile time because you're changing the ICMPType at run time.
I would suggest:
Make an enum for each of the code ranges you want to represent.
Create a container for each type (i.e. multiple ICMPHeader types specific to each type and lose the type variable there).
Create a factory which takes your original ICMP header and produces one of the specialised types with the appropriate ICMPType enum.
That should be a pretty flexible approach, but simply casting the value of the code depending on the type would probably be enough and much easier to handle.
In your example you just cast back to an int though which strips everything you just set out to achieve.. ?
Edit - if all your containers inherited from a common base class you could gave a generic GetDescription() method which the children could then populate. Abstracting the details away like this makes for a nice clean design...
Perhaps something similar has already been asked, and sure, it's a nitpick...
I have a bunch of constant std::maps to switch between enum (class) values and their std::string representations (both ways). Someone here pointed out to me that these maps will be initialized at runtime, when other initialization code is run, before my program executes all the good stuff. This would mean constant expressions would impact runtime performance, as the maps are built up from their enum-string pairs.
As an illustrative example, here is an example of one of these maps:
enum class os
{
Windows,
Linux,
MacOSX
};
const map<string, os> os_map =
{ {"windows", os::Windows},
{"linux", os::Linux},
{"mac", os::MacOSX} };
const map<os, string> os_map_inverse =
{ {os::Windows, "windows"},
{os::Linux, "linux"},
{os::MacOSX, "mac"} };
Would the C++11 constexpr have any influence on performance, or is my assumption of a runtime initialization penalty false? I would think a compiler can embed a constant STL container as pure data in the executable, but apparently that may not be as easy as I make it sound?
It's not so much the performance of initialization that is a problem, but the order of initialization. If someone uses your map before main has started (for example at initialization for a namespace scope variable), then you are SOL, because you are not guaranteed that your map has been initialized before the user's initialization uses it.
However you can do this thing at compile time. String literals are constant expressions, as are enumerators. A simple linear-time complexity structure
struct entry {
char const *name;
os value;
};
constexpr entry map[] = {
{ "windows", os::Windows },
{ "linux", os::Linux },
{ "mac", os::Mac }
};
constexpr bool same(char const *x, char const *y) {
return !*x && !*y ? true : (*x == *y && same(x+1, y+1));
}
constexpr os value(char const *name, entry const *entries) {
return same(entries->name, name) ? entries->value : value(name, entries+1);
}
If you use value(a, b) in a constant expression context, and the name you specify doesn't exist, you will get a compile time error because the function call would become non-constant.
To use value(a, b) in a non-constant expression context, you better add safety features, like adding an end marker to your array and throwing an exception in value if you hit the end marker (the function call will still be a constant expression as long as you never hit the end marker).
constexpr does not work on arbitrary expressions, and especially not on things that will use the freestore. map/string will use the freestore, and thus constexpr will not work for initializing them at compile time, and have no code run at runtime.
As for the runtime penalty: Depending on the storage duration of those variables (and I assume static here, which means initialization before main), you will not even be able to measure the penalty, especially not in the code that is using them, assuming you will use them many times, where the lookup has much more "overhead" than the initialization.
But as for everything, remember rule one: Make things work. Profile. Make things fast. In this order.
Ah yes, it's a typical issue.
The only alternative I've found to avoid this runtime initialization is to use plain C structures. If you're willing to go the extra-mile and store the values in a plain C array, you can get static initialization (and reduced memory footprint).
It's one of the reason LLVM/Clang actually use the tblgen utility: plain tables are statically initialized, and you can generate them sorted.
Another solution would be to create a dedicated function instead: for the enum to string conversion it's easy to use a switch and let the compiler optimize it into a plain table, for the string to enum it's a bit more involved (you need if/else branches organized right to get the O(log N) behavior) but for small enums a linear search is as good anyway, in which case a single macro hackery (based off Boost Preprocessor goodness) can get you everything you need.
I have recently found my own best way to furnish an enum. See the code:
enum State {
INIT, OK, ENoFou, EWroTy, EWroVa
};
struct StateToString {
State state;
const char *name;
const char *description;
public:
constexpr StateToString(State const& st)
: state(st)
, name("Unknown")
, description("Unknown")
{
switch(st){
case INIT : name = "INIT" , description="INIT"; break;
case OK : name = "OK" , description="OK"; break;
case ENoFou: name = "ENoFou", description="Error: Not found"; break;
case EWroTy: name = "EWroTy", description="Error: Wrong type"; break;
case EWroVa: name = "EWroVa", description="Error: Wrong value, setter rejected"; break;
// Do not use default to receive a comile-time warning about not all values of enumeration are handled. Need `-Wswitch-enum` in GCC
}
}
};
Extending this example to some universal code, let's name it lib code:
/// Concept of Compile time meta information about (enum) value.
/// This is the best implementation because:
/// - compile-time resolvable using `constexpr name = CtMetaInfo<T>(value)`
/// - enum type can be implemented anywhere
/// - compile-time check for errors, no hidden run-time surprises allowed - guarantied by design.
/// - with GCC's `-Wswitch` or `-Werror=switch` - you will never forget to handle every enumerated value
/// - nice and simple syntaxis `CtMetaInfo(enumValue).name`
/// - designed for enums suitable for everything
/// - no dependencies
/// Recommendations:
/// - write `using TypeToString = CtMetaInfo<Type>;` to simplify code reading
/// - always check constexpr functions assigning their return results to constexpr values
/**\code
template< typename T >
concept CtMetaInfo_CONCEPT {
T value;
const char *name;
// Here could add variables for any other meta information. All vars must be filled either by default values or in ctor init list
public:
///\param defaultName will be stored to `name` if constructor body will not reassign it
constexpr CtMetaInfoBase( T const& val, const char* defaultName="Unknown" );
};
\endcode
*/
/// Pre-declare struct template. Specializations must be defined.
template< typename T >
struct CtMetaInfo;
/// Template specialization gives flexibility, i.e. to define such function templates
template <typename T>
constexpr const char* GetNameOfValue(T const& ty)
{ return CtMetaInfo<T>(ty).name; }
User must define specialization for user's type:
/// Specialization for `rapidjson::Type`
template<>
struct CtMetaInfo<Type> {
using T = Type;
T value;
const char *name;
public:
constexpr CtMetaInfo(T const& val)
: value(val)
, name("Unknown")
{
switch(val){
case kNullType : name = "Null" ; break;
case kFalseType: case kTrueType: name = "Bool" ; break;
case kObjectType : name = "Object"; break;
case kArrayType : name = "Array" ; break;
case kStringType : name = "String"; break;
case kNumberType : name = "Number"; break;
}
}
static constexpr const char* Name(T const& val){
return CtMetaInfo<Type>(val).name;
}
};
/// TEST
constexpr const char *test_constexprvalue = CtMetaInfo<Type>(kStringType).name;
constexpr const char *test_constexprvalu2 = GetNameOfValue(kNullType);
Is there a way in C++ to extend/"inherit" enums?
I.E:
enum Enum {A,B,C};
enum EnumEx : public Enum {D,E,F};
or at least define a conversion between them?
No, there is not.
enum are really the poor thing in C++, and that's unfortunate of course.
Even the class enum introduced in C++0x does not address this extensibility issue (though they do some things for type safety at least).
The only advantage of enum is that they do not exist: they offer some type safety while not imposing any runtime overhead as they are substituted by the compiler directly.
If you want such a beast, you'll have to work yourself:
create a class MyEnum, that contains an int (basically)
create named constructors for each of the interesting values
you may now extend your class (adding named constructors) at will...
That's a workaround though, I have never found a satistifying way of dealing with an enumeration...
I've solved in this way:
typedef enum
{
#include "NetProtocols.def"
} eNetProtocols, eNP;
Of course, if you add a new net protocol in the NetProtocols.def file, you have to recompile, but at least it's expandable.
"NetProtocols.def" will contain only the field names:
HTTP,
HTTPS,
FTP
I had this problem in some projects that ran on small hardware devices I design. There is a common project that holds a number of services. Some of these services use enums as parameters to get additional type checking and safety. I needed to be able to extend these enums in the projects that use these services.
As other people have mentioned c++ doesn't allow you to extend enums. You can however emulate enums using a namespace and a template that has all the benefits of enum class.
enum class has the following benefits:
Converts to a known integer type.
Is a value type
Is constexpr by default and takes up no valuable RAM on small processors
Is scoped and accessible by enum::value
Works in case statements
Provides type safety when used as a parameter and needs to be explicitly cast
Now if you define a class as an enum you can't create constexpr instances of the enum in the class declaration, because the class is not yet complete and it leads to a compile error. Also even if this worked you could not extend the value set of enums easily later in another file/sub project .
Now namespaces have no such problem but they don't provide type safety.
The answer is to first create a templated base class which allows enums of different base sizes so we don't waste what we don't use.
template <typename TYPE>
class EnumClass {
private:
TYPE value_;
public:
explicit constexpr EnumClass(TYPE value) :
value_(value){
}
constexpr EnumClass() = default;
~EnumClass() = default;
constexpr explicit EnumClass(const EnumClass &) = default;
constexpr EnumClass &operator=(const EnumClass &) = default;
constexpr operator TYPE() const {return value_;}
constexpr TYPE value() const {return value_;}
};
Then for each enum class we want to extend and emulate we create a namespace and a Type like this:
namespace EnumName {
class Type :public Enum<uint8_t> {
public:
explicit constexpr Type(uint8_t value): Enum<uint8_t>(value){}
constexpr Enum() = default;
}
constexpr auto Value1 = Type(1);
constexpr auto Value2 = Type(2);
constexpr auto Value3 = Type(3);
}
Then later in your code if you have included the original EnumName you can do this:
namespace EnumName {
constexpr auto Value4 = Type(4U);
constexpr auto Value5 = Type(5U);
constexpr auto Value6 = Type(6U);
constexpr std::array<Type, 6U> Set = {Value1, Value2, Value3, Value4, Value5, Value6};
}
now you can use the Enum like this:
#include <iostream>
void fn(EnumName::Type val){
if( val != EnumName::Value1 ){
std::cout << val;
}
}
int main(){
for( auto e :EnumName::Set){
switch(e){
case EnumName::Value1:
std::cout << "a";
break;
case EnumName::Value4:
std::cout << "b";
break;
default:
fn(e);
}
}
}
So we have a case statement, enum comparisons, parameter type safety and its all extensible. Note the set is constexpr and wont end up using valuable RAM on a small micro (placement verified on Godbolt.org. :-). As a bonus we have the ability to iterate over a set of enum values.
If you were able to create a subclass of an enum it'd have to work the other way around.
The set of instances in a sub-class is a subset of the instances in the super-class. Think about the standard "Shape" example. The Shape class represents the set of all Shapes. The Circle class, its subclass, represents the subset of Shapes that are Circles.
So to be consistent, a subclass of an enum would have to contain a subset of the elements in the enum it inherits from.
(And no, C++ doesn't support this.)
A simple, but useful workaround for this c++ gap could be as follows:
#define ENUM_BASE_VALS A,B,C
enum Enum {ENUM_BASE_VALS};
enum EnumEx {ENUM_BASE_VALS, D,E,F};
Actually you can extend enums in a round about way.
The C++ standard defines the valid enum values to be all the valid values of the underlying type so the following is valid C++ (11+). Its not Undefined Behaviour, but it is very nasty - you have been warned.
#include <cstdint>
enum Test1:unit8_t {
Value1 =0,
Value2 =1
};
constexpr auto Value3 = static_cast<Test1>(3);
constexpr auto Value4 = static_cast<Test1>(4);
constexpr auto Value5 = static_cast<Test1>(5);
Test1 fn(Test1 val){
switch(val){
case Value1:
case Value2:
case Value3:
case Value4:
return Value1;
case Value5:
return Value5;
}
}
int main(){
return static_cast<uint8_t>(fn(Value5));
}
Note that most of the compilers don't consider the additional values as part of the set for generating warnings about missing enums values in switch statements.So
clang and gcc will warn if Value2 is missing but will do nothing if Value4 is missing in the above switch statement.
One might try this :)
struct EnumType
{
enum
{
None = 0,
Value_1 = 1,
Value_2 = 2,
Value_3 = 3
};
//For when using the EnumType as a variable type
int Value { None };
};
struct EnumTypeEx : EnumType
{
enum
{
ExValue_1 = 3,
ExValue_2 = 4,
//override the value of Value_3
Value_3 = 3000
};
};
Pros:
Class like extensibility
Can override base labels value
Cons:
Tedious to write
You have to explicitly set the value for each label(*)
(*) you can start the auto value increment from the last base value by just writing it explicitly eg. ExValue_Start = LastBaseValue.
I do this
enum OPC_t // frame Operation Codes
{
OPC_CVSND = 0 // Send CV value
, OPC_CVREQ = 1 // Request CV (only valid for master app)
, OPC_COMND = 2 // Command
, OPC_HRTBT = 3 // Heart Beat
};
enum rxStatus_t // this extends OPC_t
{
RX_CVSND = OPC_CVSND // Send CV value
, RX_CVREQ = OPC_CVREQ // Request CV
, RX_COMND = OPC_COMND // Command
, RX_HRTBT = OPC_HRTBT // Heart Beat
, RX_NONE // No new Rx
, RX_NEWCHIP // new chip detected
};
http://www.codeproject.com/KB/cpp/InheritEnum.aspx goes over a method to created an expanded enum.
Create InheritEnum.h:
// -- InheritEnum.h
template <typename EnumT, typename BaseEnumT>
class InheritEnum
{
public:
InheritEnum() {}
InheritEnum(EnumT e)
: enum_(e)
{}
InheritEnum(BaseEnumT e)
: baseEnum_(e)
{}
explicit InheritEnum( int val )
: enum_(static_cast<EnumT>(val))
{}
operator EnumT() const { return enum_; }
private:
// Note - the value is declared as a union mainly for as a debugging aid. If
// the union is undesired and you have other methods of debugging, change it
// to either of EnumT and do a cast for the constructor that accepts BaseEnumT.
union
{
EnumT enum_;
BaseEnumT baseEnum_;
};
};
And then to use:
enum Fruit { Orange, Mango, Banana };
enum NewFruits { Apple, Pear };
typedef InheritEnum< NewFruit, Fruit > MyFruit;
void consume(MyFruit myfruit);
YMMV.
Just an idea:
You could try to create an empty class for each constant (maybe put them all in the same file to reduce clutter), create one instance of each class and use the pointers to these instances as the "constants". That way, the compiler will understand inheritance and will perform any ChildPointer-to-ParentPointer conversion necessary when using function calls, AND you still get type-safety checks by the compiler to ensure no one passes an invalid int value to functions (which would have to be used if you use the LAST value method to "extend" the enum).
Haven't fully thought this through though so any comments on this approach are welcome.
And I'll try to post an example of what I mean as soon as I have some time.
My approach slightly differs from that chosen by Marco.
I have added a macro as the last value of the enum I want to extend. In a separate header, I have defined that macro with the enum entries I want to add.
// error.h
#ifndef __APP_DEFINED__
#define __APP_DEFINED__
#endif
typedef enum { a, b, c, __APP_DEFINED__ } Error;
To add more values, I have created
// app_error.h
#define __APP_DEFINED__ d, e, f,
Lastly, I have added -include app_error.h to the compiler flags.
I prefer this approach compared to placing an #include "app_error.h" directive within the enum, mainly because I need the freedom not to have the "app_error.h" file at all in some projects.
The following code works well.
enum Enum {A,B,C};
enum EnumEx {D=C+1,E,F};