Can we define an enum variable like an array? [duplicate] - c++

This question already has answers here:
How to cast int to enum in C++?
(6 answers)
Closed last year.
i have below enum :
enum words= {dog, cat, horse, hen, goat, pig, sheep};
can i assign a new enum constant as below :
words word = words[4];
What i want to do is get a random number between 0 and words.size() .and i want to pick that word from the enum . is it possible?
int wordno = (rand()%8);
words word = (words)wordno;

Your enum declaration is a bit wrong. It should be
enum words {dog, cat, horse, hen, goat, pig, sheep};
Since C++11 it is usually also better to use an enum class instead, see this question for details:
enum class words {dog, cat, horse, hen, goat, pig, sheep};
Note that enum enumerators already have a numeric value. If you don't specify these numeric values manually, they are from left-to-right starting from zero increasing by one. So e.g. horse has the numeric value 2 in your enumeration.
However, it is not directly allowed to convert between the numeric value and the enumeration implicitly. If you need to do that, you must use static_cast:
auto word = static_cast<words>(wordno);
When doing this, you need to be careful however (which is also why the explicit cast is required), because you are not allowed to cast an integer value that is outside the range of numeric values of the enumeration in this way. In your code you do rand()%8 which can return values up to 7, but the largest numeric value in your enumeration is 6 for sheep. You would have undefined behavior with that.
auto can be replaced by words. It just lets the compiler figure out the correct type, so I don't have to write it twice. (It is already in the static_cast.)
As a sidenote, rand is not a good random number generator for many reasons (see e.g. this question). Since C++11 you can use the more modern <random> library, see this question.
Also as a sidenote I suggest avoiding C-style casts such as (words)wordno. Instead use static_cast as I showed above. You are much less likely to make serious mistakes this way, since the C-style casts are usually too permissive in what casts they allow.
For words word = words[4];, this syntax does not work. But it is not really necessary, since as above, you can initialize word directly with the value 4 with an explicit cast.
auto word = static_cast<words>(4);
But if you are intending to assign a constant value, you should just use the enumerator directly. That is what they are for:
auto word = words::goat;

Related

Why can't I use a 'str[0]' to decode an enum in C++? [duplicate]

This question already has answers here:
C: Map string to ENUM [duplicate]
(2 answers)
Closed 2 years ago.
I'm parsing a string coming from a 'black box' screen controller and thought I'd be able to use enum to interpret the various parameters. I'm trying to understand why my approach won't work and although I know its something to do with types and casts I can't seem to reach a conclusion. I'd like to know if its just fundamentally a wrong approach or I'm missing something more basic. The stream arrives as a string array terminated with \n and I split it but then need to analyse the first letter of each 'token' dealing with the value according to what 'letter' is in 'str[0]'.
obviously didn't get the point across, I'm not looking for a coded solution just an understanding of where my wrong assumptions are.
enum TL_parEnum : char {X = 0, Y = 1, Z = 2};
struct TL_params {
bool seen;
float value;
};
TL_params TL_parbuffer[9]{false,0};
while (TL_parsub = strtok_r(TL_param, " ", &TL_param)) {
char p = TL_parsub[0];
switch (TL_parsub[0]) {
case 'Y' :
TL_parbuffer[p].seen=true;
TL_parbuffer[(TL_parEnum)p].value =atoi(&TL_parsub[1]);
}
the above fails because (TL_parEnum)p doesn't evaluate through the enum I either get the char 'Y' or the ascii 59. BUT if I hardcode (TL_parnum)Y it works as expected.
I've tried casting to and from char, *char, even my own constructions like TL_parEnum(j) but I only get the ascii code or the letter not something that I can use to 'decode' the enum.
So am I making poor assumptions about how this should work?
Also this is for an embedded controller so I don't have access to all the C++ goodies and I'm wondering if that is a factor.
enums are largely a compile-time feature; the fact that it's named Y isn't relevant once the code is compiled (aside from in debugging symbols). You can't convert from a character describing the name of an enum member to the member itself without manually coding a lookup table for it in some way. Even if j[0] contains 'Y', the program has no idea that that maps to the member Y with value 1 when it's time to execute the code.
If you want to enable this sort of conversion, I'd recommend writing a simple function with a switch statement for char that has cases for each ASCII character covered, and returns the appropriate enum member (with a default that raises an exception or terminates the program when an unrecognized character is provided).

C++ doubly enum value assignment

In an open source code I found an enum initialization that looked like that:
enum example {
FIRST,
FIRST_AGAIN = FIRST,
SECOND,
ETC
};
I was surprised how the values of the enum are going to be initialized, because the FIRST_AGAIN would get the value 0 because FIRST is 0, too. But i thought it could affect the FIRST value to be -1, when the FIRST_AGAIN value is 0.
So I looked with the debugger what values are assigned to the key words. FIRST and FIRST_AGAIN are assigned with 0.
So, my question is, is it really allowed (GCC compiles it, but what does the C++ standard say?) to assign two key words in an enumaration with the same value? And how does the compiler translate the assignment? Because to know the value of FIRST, the compiler should gone through the whole enum first and look if any key word is assigned, back from there, he could assign all the other values, but he doesn't know what the assignment FIRST_AGAIN = FIRST means.
Maybe the question is stupid and it's common use to do something like that. What would be the benefits of assigning two key words with the same value?
So, my question is, is it really allowed (GCC compiles it, but what does the C++ standard say?) to assign two key words in an enumaration with the same value?
That's fine. The C++ standard doesn't say anything about it in the normative text, so it's implicitly allowed, but does include an example:
enum { a, b, c=0 };
Which defines a and c as zero.
And how does the compiler translate the assignment? Because to know the value of FIRST, the compiler should gone through the whole enum first
No, the compiler doesn't need to do that. An enumerator definition without an explicit value doesn't depend on later enumerator definitions. Its value is the value of the previous enumerator plus one, or zero if there were no previous enumerators.
Maybe the question is stupid and it's common use to do something like that. What would be the benefits of assigning two key words with the same value?
One possibility:
enum E {
A = 20,
B = 30,
C = 40,
MIN = A,
MAX = C
}
Here, it may be expected that the values of MIN and MAX may change as enumerators are added or removed, but the values of A, B and C are expected to remain constant. By using C where C is wanted, and MIN and MAX where a range is wanted, code may be future-proof for later versions of whatever library defines this enumeration.

Enum co-variance/polymorphism?

Imagine I have an enum defining a common option like:
enum valueState
{
uninitialized,
min,
max
}
Now imagine I have a more specific value state for specific value types, lets say:
enum floatValueState
{
nan
}
Would there be any way to pass the valueState options as floatValueStates ? Or is there some other way to achieve this kind of abstraction of choices at compile time without too much template noise.
EDIT:
Ofc they can implicitly convert to the type of enum, but how would you combine the two enums without overlapping values (like 0 = uninitialized, 4 = non) without specifying how many enums I will combine.
Because old style enums (non-class) are just integers (implicit conversion), you can pass them around with disregard to which you're actually using. This is dangerous, but allows you to do what you want easily. You would need to micro-manage the values though, to make sure nan and uninitialized are not the same thing:
enum floatValueState {
nan = 3
}
Anything accepting a floatValueState will implicitly accept a ValueState, with no extra work - what you want, but again, dangerous. Specifically, anything accepting a ValueState will also accept a floatValueState - and that could break stuff.
Whilst it is technically possible to solve this (see the other answer) - there is some theoretical problem: this is probably a violation of the Liskov Substitution Principle. That principle guides us how to use inheritance in sound OO design.
And it states: each "usage" of the "base type" - you can insert the "derived type" there.
Given that context - how would you "embed" that "additional information nan" here?
In other words (pseudo code):
valueState value = ...
if (value == min || max) {
... } else {
value must be uninitialized
But what if value would now be floatValueState?!

Confusion between constants and literals?

I am currently reading about constants on the c++ tutorial from TutorialsPoint and, where it says:
Constants refer to fixed values that the program may not alter and they are called literals.
(Source)
I do not really get this. If constants are called literals and literals are data represented directly in the code, how can constants be considered as literals? I mean variables preceded with the const keyword are constants, but they are not literals, so how can you say that constants are literals?
Here:
const int MEANING = 42;
the value MEANING is a constant, 42 is a literal. There is no real relationship between the two terms, as can be seen here:
int n = 42;
where n is not a constant, but 42 is still a literal.
The major difference is that a constant may have an address in memory (if you write some code that needs such an address), whereas a literal never has an address.
I disagree with the claim "...There wasn't a thing called const in C originally so this was fine." const is actually one of the 32 C keywords. Google to see.
With that rested, I think the man missed something at TP. To be fair to them at Tutorials Point, they had an article that explained the difference thus (full quote, verbatim):
https://www.tutorialspoint.com/questions/category/Cplusplus
A literal is a value that is expressed as itself. For example, the number 25 or the string "Hello World" are both literals.
A constant is a data type that substitutes a literal. Constants are used when a specific, unchanging value is used various times during the program. For example, if you have a constant named PI that you'll be using at various places in your program to find the area, circumference, etc of a circle, this is a constant as you'll be reusing its value. But when you'll be declaring it as:
const float PI = 3.141;
The 3.141 is a literal that you're using. It doesn't have any memory address of its own and just sits in the source code.
Pls don't disparage those fellows doing what you call "random tutorials". Kids from poorer homes and less developed world can't afford your " good C++ textbooks " e.g. Scott Myers Effective C++ It is these online free tutorials they can have, and most of these tutorials do better explaining than the "good books".
By any means read them guys. Get confused some then come over here to StackOveflow or Quora to have your confusion cleared. Happy coding guys.
The author of the article is confused, and spreading that confusion to others (including you).
In C, literals are "constants". There wasn't a thing called const in C originally so this was fine.
C++ is a different language. In C++, literals are called "literals", and "constant" has a few meanings but generally is a const thing. The two concepts are different (although both kinds of things cannot be mutated after initial creation). We also have compile-time constants via constexpr which is yet another thing.
In general, read a good book rather than random tutorials written by randomers on the internet!
While the first part of the statement makes sense
Constants refer to fixed values that the program may not alter
the continuation
and they are called literals
is not really true.
Neil has already explained the semantical difference between the literal and the constant in his answer. But I would also like to add that the values of constant variables in C++ are not necessarily known at compile time.
// x might be obtained at runtime
// for instance, from the user input
void print_square(int x)
{
const int square = x*x;
std::cout << square << '\n';
}
Literals are values that are known at compile-time, which allows the compiler to put them to a separate read-only address space in the resulting binaries.
You can also enforce your variables to be known at compile-time by applying constexpr keyword (C++11).
constexpr int meaning = 42;
P.S. And I also do agree with a comment suggesting to use a good book instead of tutorialspoint.
If constants are called literals and literals are data represented directly in the code, how can constants be considered as literals?
The article from which you drew the quote is defining the word "constant" to be a synonym of "literal". The latter is the C++ standard's term for what it is describing. The former is what the C standard uses for the same concept.
I mean variables preceded with the const keyword are constants, but they are not literals, so how can you say that constants are literals?
And there you are providing an alternative definition for the term "constant", which, you are right, is inconsistent with the other. That's all. TP is using a different definition of the term than the one you are used to.
In truth, although the noun usage of "constant" appears in a couple of places in the C++ standard outside the defined term "null pointer constant", apparently with the meaning you propose here, I do not find an actual definition of that term, and especially not one matching yours. In truth, your definition is less plausible than TutorialPoint's, because an expression having const-qualified type can nevertheless designate an object that is modifiable (via a different expression).
Constant is simply a variable declared constant by keyword 'const' whose value after being declared shouldn't be altered during the course of the program (and if tried to alter it will result in an error).
On the other hand, literal is simply what is used and represented as it is typed in. For example, 25 when used in an expression (x+4*y+25) will be termed as literal.
Whenever we use String values or directly supply it in double quotes ("hello"), then that value in double quotes is called literal.
For example, printf("This is literal");
And if you are assigning a string value to a variable then thereafter you will refer to the variable (which could be declared constant if desired) and not exclusively to the value you have stored in it, i.e., only till the point you are supplying a value (string type of any other type) to the variable, the value is referred to as literal value, after that the variable is talked about whenever referring that value.
Once again, the value(25) in expression : x+4*y+25 is literal.
The value(4) in the term 4*y is also a literal (since it is exactly as we see it and is known to compiler beforehand).
--> The value(4) in the term 4*y is called numerical coefficient in algebraic terms and y is called literal coefficient in algebraic terms.
Hence,
All the above explanation I have given is in computer terms only. The meaning of literals and constants in Algebra are somewhat different than used in computer terms.
"Constants refer to fixed values that the program may not alter and they are called literals. (Source)"
The sentence construction is weird which is leading to the confusion.
Here, the the "they" that are referring to are the the fixed values and not constants. I would phrase it as "Constants refer to fixed values, that the program may not alter, called literals." which is less confusing I hope.
Constants are variables that can't vary, whereas Literals are literally numbers/letters that indicate the value of a variable or constant.
I can explain it this way.
Basically, constants are variables whose value cannot change.
Literals are notations that represent fixed values. These values can be Strings numbers etc
Literals can be assigned to variables
Code :
var a = 10;
var name = "Simba";
const pi = 3.14;
Here a and name are variables. pi is a constant. ( Constants are those variables whose value doesn't change. )
Here 10, "Simba" and 3.14 are literals.

Assigning values to enum

While doing a review of some older code, I notice the following two strange constructions using enum (two different files/classes/namespaces, just putting them together here):
enum FirstEnum
{
A_CHOICE
,ANOTHER_CHOICE=1
,YET_SOME_OTHER_CHOICE
};
enum SecondEnum
{
FIRST_CHOICE
,SECOND_CHOICE
,THIRD_CHOICE
,DEFAULT_CHOICE=SECOND_CHOICE
};
I think both constructions are wrong.
The first one assigns a value to one of the choices, but not to the others, meaning that things might go wrong if new choices are added.
In the second case, we end up with two enumeration elements having the same underlying value.
Is there any reason why the C++ standard allows both constructions?
(using Visual Studio 2010)
The first one assigns a value to one of the choices, but not to the others, meaning that things might go wrong if new choices are added.
I don't know what you mean by "go wrong". It's well-defined that if you don't specify a value for an enumerator, its value is one more than the previous (or zero, if it's the first).
In the second case, we end up with two enumeration elements having the same underlying value.
Yes we do. That would be wrong if enumerations were supposed to be a set of unique values but (in C++) they aren't.
Is there any reason why the C++ standard allows both constructions?
Because, in C++, an enumeration is simply a way to declare a set of related, named, constant values. It doesn't try to restrict what values they can take.
This article from Microsoft should help:
http://msdn.microsoft.com/en-us/library/2dzy4k6e(v=VS.80).aspx
The first one assigns a value to one of the choices, but not to the others
By default, the first enumerator has a value of 0, and each successive enumerator is one larger than the value of the previous one, unless you explicitly specify a value for a particular enumerator.
In the second case, we end up with two enumeration elements having the same underlying value.
Enumerators needn't have unique values within an enumeration. The name of each enumerator is treated as a constant and must be unique within the scope where the enum is defined.
The article includes examples of how these features could be taken advantage of.
I don't have a quote from the standard for you, but enums are specified such that uninitialized values take on a value one larger than the value preceding them.
In the FirstEnum, YET_SOME_OTHER_CHOICE would therefore be 2 (ANOTHER_CHOICE+1). It is also perfectly legal to have multiple equivalent values within an enum.
The first one assigns a value to one of the choices, but not to the others, meaning that things might go wrong if new choices are added.
What might go wrong? Sure, if somebody changes the first example to
enum FirstEnum
{
A_CHOICE //0
,A_THIRD_CHOICE //1
,ANOTHER_CHOICE=1 //1
,YET_SOME_OTHER_CHOICE //2
};
Then yes, they will get problems if they didn't expect two values to be the same in the enum. The same if somebody had #defined these values, and accidentally made two of them the same.
And for your second example, the names of the values in the enumeration give a hint as to why that is useful. You can have a default value for variables of type SecondEnum stored in the definition of SecondEnum, allowing you to do things like
SecondEnum var = DEFAULT_CHOICE;
without the need for #defines or constants that are closely coupled to the enum definition but aren't part of it.
Is there any reason why the C++ standard allows both constructions?
I'm not on the standards committee, but if I were to guess, it's because both constructions are useful for programmers.