error when declaring an enum to a variable - c++

I have the following syntax:
enum home
{
no,
yes,
}homew;
home homes;
std::string s;
s="no";
homes=s; //is not working. Why?
Were am I wrong?

You are confusing strings with enumerated values.
An enum variable is simply an integer that you can use a literal for at compile time, nothing more than that.
It makes the code more understandable and self-documenting rather than merely using a number literal.

This
enum home { no, yes, } homew;
defines the type home plus a variable homew of that type.
Did you intent that? Why?
The values defined for an enum type are literals, to be used as such:
home homes = no;
In C++ there's no built-in way to convert between enum value literals and a string representation of them. If you need this, you'll have to cook up your own.

enums in C++ are implicitly an int data type. You can't assign string values to enum.

It doesn't compile because C++ provides no built-in mechanism for converting from std::string to an enum.

typeof(home) != typeof(std::string) // types are not equal
Thus, you cannot assign an enum to std::string or otherwise. Implicit conversion between enum and integral types like bool, int etc. is possible however.
Is there a way I can solve my problem as it is?
If possible use std::map.
std::map<std::string, home> myTypes;
myTypes["yes"] = yes;
myTypes["no"] = no;
Now you can do,
homes = myTypes["no"];

As others pointed out, enums values are of int type. You could instead write a small function that converts from enum to String like this:
std::string GetStringFromEnum(home iHome)
{
switch (home)
{
case yes: return "yes";
case no: return "no"; break;
default: return "here be dragons";
}
}
and vice-versa:
home GetEnumFromString(std::string iImput)
{
if (iImput == "yes") return yes;
return no; //if you extend the enum beyond 2 values, this function will get more complicated
}
and you could modify your code like so:
homes = GetStringFromEnum(no)
the downside for this approach is that if you modify the enum, you must also modify the convert function.
HTH,JP

Related

I need help writing a function that checks the data type of another variable

Hi i'm having trouble making a function that checks the data type of a variable and checks it to make sure if a data type is similar to it in C++. Here's my code so far:
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
int typeCheck(string words, string typeWanted);
//make number assurance function .
string word;
cin >> word;
typeCheck(word, "string");
}
int typeCheck(string words, string typeWanted) {
if (typeid(words).name() != typeid(typeWanted).name()) {
cin.clear();
cin.ignore();
return 0;
}
else if (typeid(words).name()== typeid(typeWanted).name())
cout << "All good";
}
When I run the code it keeps saying the same output which is: All good even if I put a string or an int when its not the correct one. Instead of saying this I want it to clear the buffer and ignore it. Can anyone help me with this problem? Thanks in advance!
C++ is a statically typed language, meaning that the type is known at compile time. It will never be known only at run time.
What that means is that in your example:
int typeCheck(string words, string typeWanted);
both words and typeWanted will always be strings. If it is ever not a string, it will fail to compile. Thus, using typeid() in this situation is somewhat pointless. Your if statement will always be false, and your else-if statement will always be true.
Instead, you would want to use typeid() when you don't know they will be the same type, like in some sort of template situation:
template <class WordsType, class TypeWantedType>
int typeCheck(WordsType words, TypeWantedType typeWanted);
Here, a typeid() comparison makes more sense, because you don't really know if words and typeWanted are both strings.
You could do something like this instead:
template <class WordsType>
int typeCheck(WordsType words, string typeWanted) {
if (typeid(words).name() != typeWanted) {
//...
}
// ...
}
This would compare an unknown type to a wanted type.
Finally, there is another option, #RSahu's option from the comments:
if(words == typeWanted) {
//...
}
This will compare the input the user gave to the string "string".
It's unclear to me what you want to do exactly, so I can't recommend which one you should use, but at least now you have a couple of options.
It is because you are converting the type to string eaither way so it will allways trigger as correct as long as it is a string in the function input.
I would recommend that you use a template type so that whatever you enter into the TypeCheck() function will retain its type.

C++ wstring to enum

I have defined an enum like this:
enum eFeature
{
eF_NONE=0,
eF_PORT_A=1,
eF_PORT_B=2,
eF_PORT_C=3,
};
I would now like to convert a wstring (which is either "0", "1", "2" or "3") to eFeature.
I tried
eFeature iThis;
iThis = _wtoi(mystring.c_str());
But the compiler tells me "A value of type 'int' can not be assigned to an entity of the type eFeature."
Can somebody help?
Thank you.
You are attempting to assign an int to an enum, which is not allowed. Leaving the wstring distraction aside, what you are doing is the equivalent of
eFeature iThis;
iThis = 42;
You first need to cast the int to the enum type:
eFeature iThis;
iThis = static_cast<eFeature>(42);
Obviously, you would need to perform some kind of range checking first.

Accessing the values of an enum defined in a struct

The struct is as follows:
struct padData
{
enum buttonsAndAxes
{
select,
start,
ps
};
};
The object of the struct:
padData pad;
I am accessing this enum as follows:
printf ("\n%d", pad.buttonsAndAxes[0]);
Error:
error: invalid use of ‘enum padData::buttonsAndAxes’
Then, I tried:
printf ("\n%d", pad::buttonsAndAxes[0]);
Error:
error: ‘pad’ is not a class or namespace
Now what? Please guide.
Compiler: gcc version 4.5.0
EDIT 1:____________________________________
printf ("\nemit: %d", padData::(select)0);
results in:
error: expected unqualified-id before ‘(’ token
My aim is to fetch the word "select" through its value 0. How to achieve that? Also, is the word "select" a string?
The enum values become names in the scope of the class. So you would use padData::select from outside the class, or just select from inside the class.
In C++11 you can qualify the enumerators with the name of the enum, giving padData::buttonsAndAxes::select from the outside and buttonsAndAxes::select from inside.
Printing the name of an enumerator is not easily done in C++, because the names are gone after compilation. You need to set up a table mapping the values to their strings by hand. If you don't supply explicit values like in your example, you can simply use an array:
enum buttonsAndAxes
{
select,
start,
ps
};
const char* buttonsAndAxesNames[] = {
"select",
"start",
"ps"
};
And then you index into that array:
printf("%s", buttonsAndAxesNames[select]);
If you want some more sophisticated approach, you can find a bunch of tricks in previous questions.
printf ("\n%d", padData::select);
Enum is not array, it is used without index.
ENUMS are mainly used for better readability of code rather than calculation facilitators. ENUMS are mainly literals which are assigned values 0,1,2 etc unless specified otherwise. So you should always use them with "::" qualification rather than as array
You seem to need a good C++ book.
Enumerations, in C and C++, are a convenient way to:
map an integral value to a "smart" name
group together values that belong together
The syntax is quite simple (in C++03):
enum <enum-name> {
<value-name-0> [= <value-0>],
<value-name-1> [= <value-1>],
...
};
Where:
<enum-name> is the name of the type that is introduced
<value-name-X> is the name of a value of the enum
<value-X> is the value given to the name, and is optional
If no value is given to a name:
if it is the first, it is set to 0
else, it is set to the value of the previous name, + 1
Here is a small example demonstrating the use of enums:
enum Color {
Blue,
Green,
Red
};
char const* name(Color c) {
switch(c) {
case Blue: return "Blue";
case Green: return "Green";
case Red: return "Red";
}
assert(0 && "Who stored crap in my enum ?");
}
This illustrates a few important points at once:
Color is a type, like a struct type or a class type. It can be typedefed and all.
an enum "value-name" is an integral constant, it can be used as template parameter or in switch cases.
an enum "value-name" is injected in the scope in which the type is declared, and not nested within. (C++11 allows to scope the values with the enum class syntax)
something else entirely could be stored in the enum, while this should not happen in well behaved applications, you can do it through casting...
What is not shown, is that an enum is under the hood a plain integer. The exact underlying type though is determined at the discretion of the compiler. There are a few rules in this choice, that should not matter to you, all you should know is that the type chosen is wide enough to contain all the values of the enum (and possibly signed if required). What it implies is that the type chosen is not necessarily a plain int.
Therefore: printf("%d", Green); is a programming error. It should be printf("%d", (int)Green);.
Another important point, is that enum names do not appear in the final binary. The names are substituted for their values directly, no runtime overhead at all. Debuggers typically retrieve the names from the debug information (if available) and substitute them back in when presenting the information to you.

how to use strcat with an ENUM?

I have an external tool which is generating an ENUM based on user inputs. Now this ENUM is being used by my C++ code where in i have to select a particular ENUM based on a variable say 'x'. The ENUMS generated are of the form 'ENUM_1', 'ENUM_2', 'ENUM_3'....so on. Now I want the code inside my code such that the appropriate ENUM is chosen based on 'x'. I tried using the strcat function like:
typedef enum ( enum_1, enum_2, enum_3...enum_n) map1;
y=(map1)strcat("enum_", x);
but it gives me the error "Cannot convert from char* to map1.
Can someone pls suggest a method of achieving this.
ThankYou
You can't do this using strcat. From the description what I understand is that you want to convert x to map1. To achieve this, you can do map1 m = (map1)(x-1); See this sample code:
typedef enum { enum_1, enum_2, enum_3} map1;
int main()
{
int x = 1;
map1 m = (map1)(x-1);
}
-1 is required because, the integer value of the enums in map1 starts from 0.
You can't do this. Well you can't do it this way...
Enums aren't evaluated by name at compile time. You'll have to try something with the preprocessor. You can create a define to do something similar. Something like:
#define fn(x) enum_##x
And then call
fn(x)
But this happens when the file gets preprocessed. So you can't access runtime variables. Judging by your code I don't think you'll be able to do what you want.
Good luck though.
Now I want the code inside my code such that the appropriate ENUM is chosen based on 'x'.
Enumerated values are constants and based on the statement I assume that x is an integer data type.
y=(map1)strcat("enum_", x);
strcat(..) passing parameters should be of type char*. And clearly x is not of type char* based on previous statement. It not clear why are you using strcat for achieving this task.
Answer for your subject line: No. You cannot use strcat with enumerated values.

Type casting in c++

In c++ can we cast an object to an integer ?
Clarifying my question - Suppose I have created an interface to handle file management task like create file, open file, read, write and I want to have one unique handle for every instance of a file. To achieve this can I create a file handle for each instance of the file interface by just type casting that instance to integer ?
To all - I hope now i am clear.
Not all objects. Every object in C++ has a type. That type of an object defines whether a cast to int exists, and if so, what algorithm is used.
If you have an object and want to cast it to int then you need to explicitly provide operator int for that class.
class File
{
public:
...
...
operator int() { return int(this); }
...
}
Then
File myFile;
int myFileHandle = myFile;
I would rather convert to a long type. This is safer when a pointer value is converted to an integral type on an x64 machine. You can just use reinterpret_cast<long>(myInterfacePointer) in that case.
you can, but it depend on the sizeof(YourObject) compared to sizeof(int), by casting any object to int you will access the first 4 bytes part of your object (assuming sizeof(int) == 4), if your object is smaller than sizeof(int) somewhere you will get access violation or crash. to cast :
`
MyObject object;
int castedObject = *((int*)&object);
`
to cast without pointer intermediate, you must provide typecast operator inside MyObject class. or you can declare global static function of int& operator=(const MyObject& object){...}
Edit: Since you are mapping files to a unique handle, you can use a std::vector<std::string> or a vector<shared_ptr<fstream> > or a vector<FILE*>.
On a POSIX-compliant system there is also fileno to convert a FILE* into its file descriptor which is an int.
To get the hash: Use the hash_value function from boost.
To convert any value to integer lexically: Use the lexical_cast<int> function from boost
To cast the value to integer: Just use (int)value.
For the above to work, the class you're going to convert needs to implement some special member functions e.g. operator<< and operator int.
To convert an object into an arbitrary unique integer, use (int)&value.
To get a random integer, use rand().
Why not just get the file descriptor/handle/whatever ID from the operating system and use that? Most systems have some kind of concept like that.
Consider using void * instead of int for the handles if you really want them to be pointers. Then casting a pointer-to-object to a handle is easy, and you can still hide the implementation away.
In response to #potatoswatter's comment to my first response.
I don't like the idea of casting objects. I would rather use a hashing function that produces an integer hash, say based on the filename or read/write flags. Now, I have to post another answer
class File
{
public:
...
...
operator int();
...
private:
char fileName[];
int flags;
};
The integer conversion operator is now a hashing function:
File::operator int()
{
int hash = 0;
int c;
char *str = fileName;
while (c = *str++)
hash += c;
hash += flags;
return hash;
}
I know the hash function is lousy. But you can avoid casts that are lousier and come up with your own hashing function that suits your needs better.