Continuous enum C++11 - c++

Is there a way to check in C++11 if an enum is continuous?
It is fully valid to give an enum values which are not. Is there maybe a feature like a type trait in C++14, C++17 or maybe C++20 to check is the enum is continuous? This to be used in a static_assert.
A small example follows:
enum class Types_Discontinuous {
A = 10,
B = 1,
C = 100
};
enum class Types_Continuous {
A = 0,
B = 1,
C = 2
};
static_assert(SOME_TEST<Types_Discontinuous>::value, "Enum should be continuous"); // Fails
static_assert(SOME_TEST<Types_Continuous>::value, "Enum should be continuous"); // Passes

This is not possible in pure C++, because there is no way to enumerate the enum values, or discover the number of the values and minimum and maximum values. But you could try using the help of your compiler to implement something close to what you want. For example, in gcc it is possible to enforce a compilation error if a switch statement does not handle all values of an enum:
enum class my_enum {
A = 0,
B = 1,
C = 2
};
#pragma GCC diagnostic push
#if __GNUC__ < 5
#pragma GCC diagnostic error "-Wswitch"
#else
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
constexpr bool is_my_enum_continuous(my_enum t = my_enum())
{
// Check that we know all enum values. Effectively works as a static assert.
switch (t)
{
// Intentionally no default case.
// The compiler will give an error if not all enum values are listed below.
case my_enum::A:
case my_enum::B:
case my_enum::C:
break;
}
// Check that the enum is continuous
auto [min, max] = std::minmax({my_enum::A, my_enum::B, my_enum::C});
return static_cast< int >(min) == 0 && static_cast< int >(max) == 2;
}
#pragma GCC diagnostic pop
Obviously, this is specialized for a given enum, but definition of such functions can be automated with preprocessor.

For a number of enums you can probably hack your way through this using the Magic Enum library. For example:
#include "magic_enum.hpp"
template <typename Enum>
constexpr bool is_continuous(Enum = Enum{}) {
// make sure we're actually testing an enum
if constexpr (!std::is_enum_v<Enum>)
return false;
else {
// get a sorted list of values in the enum
const auto values = magic_enum::enum_values<Enum>();
if (std::size(values) == 0)
return true;
// for every value, either it's the same as the last one or it's one larger
auto prev = values[0];
for (auto x : values) {
auto next = static_cast<Enum>(magic_enum::enum_integer(prev) + 1);
if (x != prev && x != next)
return false;
else
prev = x;
}
return true;
}
}
Note that this is indeed, as the library name implies, "magic" – the library functions on a number of compiler-specific hacks. As such it doesn't really meet your requirement of "pure C++", but is probably as good as we can get until we have reflection facilities in the language.

I'd love to see an answer on this. I've been needing it as well.
Unfortunately, I don't think this is possible using the existing utilities. If you want to implement a type trait on this, you need support from your compiler, so writing a template for it doesn't sound feasible.
I've already extended the enumeration with a specific tag to indicate it is contiguous and immediately gives you the size: enum class constructor c++ , how to pass specific value?
Alternatively, you can write your own trait:
template<T> struct IsContiguous : std::false_type {};
This needs to be specialized whenever you define an contiguous enum where you want to use this. Unfortunately, this requires some maintenance and attention if the enum gets changed.

All enum's are continuous. 0 is always allowed; the highest value allowed is the highest enumerator rounded up to the next 1<<N -1 (all bits one), and all values in between are allowed too. ([dcl.enum] 9.7.1/5). If there are negative enumerators defined, the lowest value allowed is similarly defined by rounding down the lowest enumerator.
The enumerators defined in the enum are constant expressions with a value in range and the correct type, but you can define additional constants outside the enum which have the same properties:
constexpr enum class Types_Discontinuous = static_cast<Types_Discontinuous>(2)

Related

Are constant "flags" considered good style? (c++)

I am currently working an a library and I wonder if it's considered good style to have all-caps constants like:
constexpr int ONLY_LOWERCASE = 1;
constexpr int ONLY_UPPERCASE = 2;
And so on. I plan on using it to let the library user control the behavior of the functions like:
doSomeThing(var, ONLY_UPPERCASE);+
Thanks
It's seems like you are using integer structure to store boolean data. It might considered as a better way to use boolean structure for this purpose, for memory usage reasons.
One way of archive this target is using enum or enum class that inherit from bool:
enum class string_case : bool {
ONLY_LOWERCASE,
ONLY_UPPERCASE
}
This way you will use a single byte that indicate whatever you want, instead of 8 bytes in your example.
Usage example:
doSomeThing(var, string_case::ONLY_UPPERCASE);
Edit
In case you have more than 2 flags, you can still use enum (just without inheritance from bool):
enum class string_case {
ONLY_LOWERCASE = 1,
ONLY_UPPERCASE = 2,
FLAG_3 = 3,
FLAG_4 = 4
};
And even so, using only 4 bytes (instead of 4(bytes) * flags_count).
Another approach, if multiple flags can be on together (and you don't want to play with bits in your enum calculations), you can use a struct:
struct options {
bool option_1: 1;
bool option_2: 1;
bool option_3: 1;
bool option_4: 1;
};
And in this way you'll only use the amount of bytes that you need to store those bits.

C++ enum flags vs bitset

What are pros/cons of usage bitsets over enum flags?
namespace Flag {
enum State {
Read = 1 << 0,
Write = 1 << 1,
Binary = 1 << 2,
};
}
namespace Plain {
enum State {
Read,
Write,
Binary,
Count
};
}
int main()
{
{
unsigned int state = Flag::Read | Flag::Binary;
std::cout << state << std::endl;
state |= Flag::Write;
state &= ~(Flag::Read | Flag::Binary);
std::cout << state << std::endl;
} {
std::bitset<Plain::Count> state;
state.set(Plain::Read);
state.set(Plain::Binary);
std::cout << state.to_ulong() << std::endl;
state.flip();
std::cout << state.to_ulong() << std::endl;
}
return 0;
}
As I can see so far, bitsets have more convinient set/clear/flip functions to deal with, but enum-flags usage is a more wide-spreaded approach.
What are possible downsides of bitsets and what and when should I use in my daily code?
Both std::bitset and c-style enum have important downsides for managing flags. First, let's consider the following example code :
namespace Flag {
enum State {
Read = 1 << 0,
Write = 1 << 1,
Binary = 1 << 2,
};
}
namespace Plain {
enum State {
Read,
Write,
Binary,
Count
};
}
void f(int);
void g(int);
void g(Flag::State);
void h(std::bitset<sizeof(Flag::State)>);
namespace system1 {
Flag::State getFlags();
}
namespace system2 {
Plain::State getFlags();
}
int main()
{
f(Flag::Read); // Flag::Read is implicitly converted to `int`, losing type safety
f(Plain::Read); // Plain::Read is also implicitly converted to `int`
auto state = Flag::Read | Flag::Write; // type is not `Flag::State` as one could expect, it is `int` instead
g(state); // This function calls the `int` overload rather than the `Flag::State` overload
auto system1State = system1::getFlags();
auto system2State = system2::getFlags();
if (system1State == system2State) {} // Compiles properly, but semantics are broken, `Flag::State`
std::bitset<sizeof(Flag::State)> flagSet; // Notice that the type of bitset only indicates the amount of bits, there's no type safety here either
std::bitset<sizeof(Plain::State)> plainSet;
// f(flagSet); bitset doesn't implicitly convert to `int`, so this wouldn't compile which is slightly better than c-style `enum`
flagSet.set(Flag::Read); // No type safety, which means that bitset
flagSet.reset(Plain::Read); // is willing to accept values from any enumeration
h(flagSet); // Both kinds of sets can be
h(plainSet); // passed to the same function
}
Even though you may think those problems are easy to spot on simple examples, they end up creeping up in every code base that builds flags on top of c-style enum and std::bitset.
So what can you do for better type safety? First, C++11's scoped enumeration is an improvement for type safety. But it hinders convenience a lot. Part of the solution is to use template-generated bitwise operators for scoped enums. Here is a great blog post which explains how it works and also provides working code : https://www.justsoftwaresolutions.co.uk/cplusplus/using-enum-classes-as-bitfields.html
Now let's see what this would look like :
enum class FlagState {
Read = 1 << 0,
Write = 1 << 1,
Binary = 1 << 2,
};
template<>
struct enable_bitmask_operators<FlagState>{
static const bool enable=true;
};
enum class PlainState {
Read,
Write,
Binary,
Count
};
void f(int);
void g(int);
void g(FlagState);
FlagState h();
namespace system1 {
FlagState getFlags();
}
namespace system2 {
PlainState getFlags();
}
int main()
{
f(FlagState::Read); // Compile error, FlagState is not an `int`
f(PlainState::Read); // Compile error, PlainState is not an `int`
auto state = FlagState::Read | FlagState::Write; // type is `FlagState` as one could expect
g(state); // This function calls the `FlagState` overload
auto system1State = system1::getFlags();
auto system2State = system2::getFlags();
if (system1State == system2State) {} // Compile error, there is no `operator==(FlagState, PlainState)`
auto someFlag = h();
if (someFlag == FlagState::Read) {} // This compiles fine, but this is another type of recurring bug
}
The last line of this example shows one problem that still cannot be caught at compile time. In some cases, comparing for equality may be what's really desired. But most of the time, what is really meant is if ((someFlag & FlagState::Read) == FlagState::Read).
In order to solve this problem, we must differentiate the type of an enumerator from the type of a bitmask. Here's an article which details an improvement on the partial solution I referred to earlier : https://dalzhim.github.io/2017/08/11/Improving-the-enum-class-bitmask/
Disclaimer : I'm the author of this later article.
When using the template-generated bitwise operators from the last article, you will get all of the benefits we demonstrated in the last piece of code, while also catching the mask == enumerator bug.
Some observations:
std::bitset< N > supports an arbitrary number of bits (e.g., more than 64 bits), whereas underlying integral types of enums are restricted to 64 bits;
std::bitset< N > can implicitly (depending on the std implementation) use the underlying integral type with the minimal size fitting the requested number of bits, whereas underlying integral types for enums need to be explicitly declared (otherwise, int will be used as the default underlying integral type);
std::bitset< N > represents a generic sequence of N bits, whereas scoped enums provide type safety that can be exploited for method overloading;
If std::bitset< N > is used as a bit mask, a typical implementation depends on an additional enum type for indexing (!= masking) purposes;
Note that the latter two observations can be combined to define a strong std::bitset type for convenience:
typename< Enum E, std::size_t N >
class BitSet : public std::bitset< N >
{
...
[[nodiscard]]
constexpr bool operator[](E pos) const;
...
};
and if the code supports some reflection to obtain the number of explicit enum values, then the number of bits can be deduced directly from the enum type.
scoped enum types do not have bitwise operator overloads (which can easily be defined once using SFINAE or concepts for all scoped and unscoped enum types, but need to be included before use) and unsoped enum types will decay to the underlying integral type;
bitwise operator overloads for enum types, require less boilerplate than std::bitset< N > (e.g., auto flags = Depth | Stencil;);
enum types support both signed and unsigned underlying integral types, whereas std::bitset< N > internally uses unsigned integral types (shift operators).
FWIIW, in my own code I mostly use std::bitset (and eastl::bitvector) as private bit/bool containers for setting/getting single bits/bools. For masking operations, I prefer scoped enum types with explicitly defined underlying types and bitwise operator overloads.
Do you compile with optimization on? It is very unlikely that there is a 24x speed factor.
To me, bitset is superior, because it manages space for you:
can be extended as much as wanted. If you have a lot of flags, you may run out of space in the int/long long version.
may take less space, if you only use just several flags (it can fit in an unsigned char/unsigned short - I'm not sure that implementations apply this optimization, though)
(Ad mode on)
You can get both: a convenient interface and max performance. And type-safety as well. https://github.com/oliora/bitmask

Reasoning behind "enumeral and non-enumeral type in conditional expression"

Since the C++11 transition GCC outputs a warning "enumeral and non-enumeral type in conditional expression". I'd like to understand the reasoning behind this warning. What are the perils of comparing enum constants?
It is obvious we can get rid of this warning by
-Wno-enum-compare
by explicitly casting to an integral type
But why the hassle? Personally, I always strive at writing warning free code, and usually the warnings emitted by default are quite sensible. For example, it figures that it's dangerous to compare signed and unsigned integers.
But using enums is widely used idiomatic C++ metaprogramming. I am not aware of any alternative, which is similarly readable, concise and to the point and does not require any actual storage.
To quote a concrete example: What can go wrong with the following metafunction, so that a warning would be adequate?
template<class TYPES>
struct MaxSize;
template<>
struct MaxSize<NullType>
{
enum{ value = 0 };
};
template<class TY, class TYPES>
struct MaxSize<Node<TY,TYPES> >
{
enum{ thisval = sizeof(TY)
, nextval = MaxSize<TYPES>::value
, value = nextval > thisval? nextval:thisval
};
};
It looks like an issue in GCC. This doesn't depend on -std=c++11 option. The warning is related not to comparison, but to the conditional operator.
Seems that the warning is issued only if one of enum members is iniatialized with an unsigned value, and another one is initialized with the value of another enum. Also, the warning is issued only in the initialization of enum members.
I managed to strip down the code to the following:
enum A { valueA = 1 };
enum B {
// if you change 0u to 0, there'll be no warning
thisval = 0u,
// if you change valueA to any integral constant, there'll be no warning
nextval = valueA,
// warning on this line
value = nextval > thisval ? nextval : thisval,
// no warning here
value2 = nextval > thisval
};
int main() {
// no warning here
(void)(nextval > thisval ? nextval : thisval);
// the same warning also here - but not with Clang
(void)(nextval > thisval ? nextval : false);
}
Online demo
Clang doesn't issue any warnings on this code (except that with -Weverything it complains about unreachable code), though it could really say something on the last line.
(GCC 4.9.2, Clang 3.5.0)
If you are using the enum as a way to define a compile time constant value , you can stop doing that now.
Use this instead:
constexpr int myConstant = 123;
where int can be anything that qualifies as a literal type [I won't try to define literal type here -- it's complicated and Google is your friend.]
Alternatively even before c++11 you could say:
class Foo{
static const int myConstant = 123;
};
where int can be any integral type.
There is no need to have the corresponding definition in a cpp file unless you need the address of myConstant somewhere.
The compiler is telling you that comparing an enum value to anything other than another value in the same enumeration is fragile code.

Comparing enums to integers

I've read that you shouldn't trust on the underlying implementation of an enum on being either signed or unsigned. From this I have concluded that you should always cast the enum value to the type that it's being compared against. Like this:
enum MyEnum { MY_ENUM_VALUE = 0 };
int i = 1;
if (i > static_cast<int>(MY_ENUM_VALUE))
{
// do stuff
}
unsigned int u = 2;
if (u > static_cast<unsigned int>(MY_ENUM_VALUE))
{
// do more stuff
}
Is this the best practice?
Edit: Does the situation change if the enum is anonymous?
An enum is an integer so you can compare it against any other integer, and even floats. The compiler will automatically convert both integers to the largest, or the enum to a double before the compare.
Now, if your enumeration is not supposed to represent a number per se, you may want to consider creating a class instead:
enum class some_name { MY_ENUM_VALUE, ... };
int i;
if(i == static_cast<int>(some_name::MY_ENUM_VALUE))
{
...
}
In that case you need a cast because an enum class is not viewed as an integer by default. This helps quite a bit to avoid bugs in case you were to misuse an enum value...
Update: also, you can now specify the type of integer of an enum. This was available in older compilers too, but it was often not working quite right (in my own experience).
enum class some_name : uint8_t { ... };
That means the enumeration uses uint8_t to store those values. Practical if you are using enumeration values in a structure used to send data over a network or save in a binary file where you need to know the exact size of the data.
When not specified, the type defaults to int.
As brought up by others, if the point of using enum is just to declare numbers, then using constexpr is probably better.
constexpr int MY_CONSTANT_VALUE = 0;
This has the same effect, only the type of MY_CONSTANT_VALUE is now an int. You could go a little further and use typedef as in:
typedef int my_type_t;
constexpr my_type_t MY_CONSTANT_VALUE = 0;
I often use enum even if I'm to use a single value when the value is not generally considered an integer. There is no set in stone rule in this case.
Short answer: Yes
enum is signed int type, but they get implicitly cast into unsigned int. Your compiler might give a warning without explicit casting, but its still very commonly used. however you should explicitly cast to make it clear to maintainers.
And of course, explicit cast will be must when its a strongly typed enum.
Best practice is not to write
int i = 1;
if (i > static_cast<int>(MY_ENUM_VALUE))
{
// do stuff
}
instead write
MyEnumValue i = MY_ENUM_VALUE ;
...
if ( i > MY_ENUM_VALUE ) {..}
But if - as in your example - you only have one value in your enum it is better to declare it as a constant instead of an enum.

C++: how to check, that enum has only unique values

we use VS 2008
there is a big enum, which is populated by many developers
this enum has a type __int64 (a Microsoft extension), and I want to make compiler complain about non unique values in enum.
if it was a usual enum I would do like this:
enum E1
{
E11 = 0x01F00,
E12 = 0x01F00,
E13
};
#pragma warning(push)
#pragma warning(error: 4061)
#pragma warning(error: 4062)
void F(E1 e1)
{
switch (e1)
{
case E11:
case E12:
case E13:
return;
}
}
#pragma warning(pop)
and the function F would have an error, if E1 has 2 same values
and it would have another error, if a developer forgot to add a new value to switch
but my enum has type __int64 (or long long)
and when I try do the same switch for E1 e1 it truncates values and complains on values, wich difference is either 0x100000000, or 0x200000000 ....
if I cast e1 to __int64, the compiler does not complain, if a developer forgets to add a new value to the switch (so the whole check function becomes useless)
the question: does someone know what I can do about it? or maybe VS 2008 (or C++) has another instrument to ensure enum : __int64 has only unique values?
From your comment I'll assume that you don't have aggregate (combined) flags within the enum itself. In that case you can use two enums to make it much harder to make mistakes. You can still subvert the compiler but I assume that's not the real problem here.
enum Bit_Index
{
FLAG1_INDEX,
FLAG2_INDEX,
FLAG_FANCY_INDEX,
LAST_INDEX
};
#define DECLARE_BIT_VALUE(att) att##_VALUE = 1ULL << att##_INDEX
enum Bit_Value
{
DECLARE_BIT_VALUE(FLAG1),
DECLARE_BIT_VALUE(FLAG2),
DECLARE_BIT_VALUE(FLAG_FANCY),
// Declared NOT using the macro so we can static assert that we didn't forget
// to add new values to this enum.
LAST_BIT // Mainly a placeholder to prevent constantly having to add new commas with new ids.
};
#undef DECLARE_BIT_VALUE
Then in an implementation file you static_assert to make sure the enums don't get misaligned:
// Make sure to the best of our abilities that we didn't mismatch the index/bit enums.
BOOST_STATIC_ASSERT((LAST_BIT - 1) == (1U << (LAST_INDEX - 1)));
Does someone know what I can do about it.
Other answer can be an algorithmic analysis. Static analysis is not necessarily a search for security vulnerabilities. Unfortunately in this case you will have to use an external tool for verification of your constraint. I can help you in implementing that.