At one point I had looked at implementing a class/template in C++ that would support an Enum that would behave like it does in Ada. It has been some time since I thought about this problem and I was wondering if anyone has ever solved this problem?
EDIT:
My apologies, I should clarify what functionality I thought were useful in the Ada implementation of the Enum. Given the enumeration
type fruit is (apple, banana, cherry, peach, grape);
We know that fruit is one of the listed fruits: apple, banana, cherry, peach, grape. Nothing really different there from C++.
What is very useful are the following pieces of functionality that you get with every enum in Ada without any additional work:
printing out an enumerated value generates the string version
you can increment the enumerated variable
you can decrement the enumerated variable
I hope this defines the problem a bit more.
Notes added from comments:
See: Wikipedia (Judah Himango, 2008-11-19 at 0:09)
See: Wikibooks
Useful features of Ada enumerations
The first value in the enumeration is fruit'first which gives apple.
The last value in the enumeration is fruit'last which gives grape.
The increment operation is fruit'succ(apple) which gives banana.
The decrement operation is fruit'pred(cherry) which also gives banana.
The conversion from enumeration to integer is fruit'pos(cherry) which returns 2 because Ada uses 0-based enumerations.
The conversion from integer to enumeration is fruit'val(2) which returns cherry.
The conversion from enumeration to string is fruit'Image(apple) which returns the (upper-case) string "APPLE".
The conversion from string to enumeration is fruit'Value("apple") which returns the value apple.
See also related SO questions:
Which Typesafe Enum in C++ Are You Using?
Next or previous enum
Okay, let's leave C++ aside for a moment. C++ is just a superset of C (which means everything that can be done in C can be done in C++ as well). So let's concentrate on plain-C (because that's a language I know well). C has enumerations:
enum fruit { apple, banana, cherry, peach, grape };
This is perfectly legal C and the values are contiguous, and apple has the value zero and banana has the value apple + 1. You can create enumerations with holes, but only if you explicitly make holes like this
enum fruit { apple = 0, banana, cherry = 20, peach, grape };
While apple is 0 and banana is 1, cherry is 20, thus peach is 21 and grape is 22 and everything between 1 and 20 is undefined. Usually you don't want holes. You can do the following:
enum fruit { apple = 0, banana, cherry, peach, grape };
enum fruit myFruit = banana;
myFruit++;
// myFruit is now cherry
printf("My fruit is cherry? %s\n", myFruit == cherry ? "YES" : "NO");
This will print YES. You can also do the following:
enum fruit { apple = 0, banana, cherry = 20, peach, grape };
enum fruit myFruit = banana;
myFruit++;
// myFruit is now cherry
printf("My fruit is cherry? %s\n", myFruit == cherry ? "YES" : "NO");
This will print NO, and the value of myFruit is not the same as any of the enumeration constants.
BTW, to avoid that you must say "enum fruit myFruit", you can avoid the enum with a typedef. Just use "typedef enum fruit fruit;" on an own line. Now you can say "fruit myFruit" without enum in front. It is often done directly when the enum is defined:
typedef enum fruit { apple = 0, banana, cherry, peach, grape } fruit;
fruit myFruit;
Disadvantage is that you don't know anymore that fruit is an enum, it might be an object, a structure or anything else. I usually avoid these type of typedefs, I rather write enum in front if an enum and struct in front if a struct (I will just use them here because it looks nicer).
Getting the string value is not possible. At runtime an enumeration is just a number. That means, it's not possible if you don't know what kind of enumeration that is (as 0 might be apple, but it might also be a different thing of a different enumeration set). However, if you know it is a fruit, then it's easy to write a function that will do it for you. The preprocessor is your friend :-)
typedef enum fruit {
apple = 0,
banana,
cherry,
peach,
grape
} fruit;
#define STR_CASE(x) case x: return #x
const char * enum_fruit_to_string(fruit f) {
switch (f) {
STR_CASE(apple); STR_CASE(banana); STR_CASE(cherry);
STR_CASE(peach); STR_CASE(grape);
}
return NULL;
}
#undef STR_CASE
static void testCall(fruit f) {
// I have no idea what fruit will be passed to me, but I know it is
// a fruit and I want to print the name at runtime
printf("I got called with fruit %s\n", enum_fruit_to_string(f));
}
int main(int argc, char ** argv) {
printf("%s\n", enum_fruit_to_string(banana));
fruit myFruit = cherry;
myFruit++; // myFruit is now peach
printf("%s\n", enum_fruit_to_string(myFruit));
// I can also pass an enumeration to a function
testCall(grape);
return 0;
}
Output:
banana
peach
I got called with fruit grape
This is exactly what you wanted or am I totally on the wrong track here?
One of my colleagues has implemented a tool to generate classes that do most (if not all) of what you want:
http://code.google.com/p/enumgen/
The current implementation is in Lisp, but do not hold that against him :-)
I wrote an enum_iterator that does this, together with a ENUM macro using Boost.Preprocessor:
#include <iostream>
#include "enum.hpp"
ENUM(FooEnum,
(N)
(A = 1)
(B = 2)
(C = 4)
(D = 8));
int main() {
litb::enum_iterator< FooEnum, litb::SparseRange<FooEnum> > i = N, end;
while(i != end) {
std::cout << i.to_string() << ": " << *i << std::endl;
++i;
}
}
It declares the enum as plain old enum, so you may still use it for "normal" purposes. The iterator can be used for other normal enums too that have sequential values, that's why it has a second template parameter which defaults to litb::ConsequtiveRange<>. It conforms to the bidirectional iterator requirements.
The silly code can be downloaded from here
There isn't an easy way to do that in C++, not least because the enumeration constants are not required to be unique or contiguous. The conversion from value to string is also non-trivial; the solutions I know of involve C/C++ Preprocessor hackery - and that is a pejorative use of the term hackery.
I'm tempted to say "No"; I'm not certain that's correct, but it most certainly is non-trivial.
you might take a look at the java enum (http://madbean.com/2004/mb2004-3/) and this idea: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
If you're interested in enumgen, I made a simple demo with
your example. As already mentioned, I implemented it using
common lisp, so the input file you write is lispy, but I
tried really hard to make the syntax reasonable.
Here it is:
$ cat Fruit.enum
(def-enum "Fruit" (("apple")
("banana")
("cherry")
("peach")
("grape")
("INVALID_")))
$ enumgen Fruit.enum
Using clisp
;; Loading file /tmp/enumgen/enumgen.lisp ...
;; Loaded file /tmp/enumgen/enumgen.lisp
loading def file:
;; Loading file /tmp/enumgen/enumgen.def ...
;; Loaded file /tmp/enumgen/enumgen.def
generating output:
Fruit.cpp
Fruit.ipp
Fruit.hpp
DONE
To view the generated code, visit this url:
http://code.google.com/p/enumgen/source/browse/#svn/trunk/demo
While it's pretty feature-rich as it is, there are a lot of things
that can be tweaked as well, by setting variables in the input file
or by specifying attributes of the enumerators.
For example, by default it represents the string names using
std::string, but it can use char const * or any user-defined string
class given a little effort.
You can have multiple names map to the same enum value, but must
pick one to be the "primary" such that mapping the value to a string
will result in this name (as opposed to the others.)
You can explicitly provide values to the enums, and they do not
need to be unique. (Duplicates are implicit aliases for the previous
enum with the same value.)
Further, you can iterate over all the unique values, and for each
value over all its aliases, which is useful if you want to
generate script-language "wrappers" for these, like we do using ruby.
If you're interested in using this and have questions, feel free to
contact me via email. (cuzdav at gmail).
Hope this helps. (There isn't a lot of documentation aside from the
test suite and demo code, and the source if you care about that.)
Chris
This article shows you how to generate the string version of an enumerated value, although it requires that you write the code to do so yourself. It also provides a preprocessor macro to very easily permit incrementing and decrementing enumerated variables, as long as your enum is continuous.
This library provides more flexible incrementing and decrementing.
The enum_rev4.6.zip library in the Boost Vault provides easy string conversions. It looks like it supports incrementing and decrementing using iterators (which is probably less convenient, but it works). It's basically undocumented, although the libs/test directory contains some good example code.
It's unreleased software but it seems BOOST_ENUM from Frank Laub could fit the bill. The part I like about it is that you can define an enum within the scope of a class which most of the Macro based enums usually don't let you do. It is located in the Boost Vault at: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=enum_rev4.6.zip&directory=&
It hasn't seen any development since 2006 so I don't know how well it compiles with the new Boost releases.
Look under libs/test for an example of usage.
There is also Boost smart_enum (not released either). It does the iterator part of your question but not the output to a string. http://cryp.to/smart-enum/
Related
I need to check if a variable is initialised. I am new to C++ so perhaps I am thinking about this in the wrong way. I want to do the following:
if (variable) {
// do some stuff
}
My first thought was to set the value to NULL at declaration. However, it turns out NULL is identical to 0 in C++. Unfortunately my variable is a double that can be 0. The solutions I could find online are all regarding pointers and just say to use nullptr but this is not possible in my case of course.
What alternatives do I have here?
General way to do this is to use std::optional
https://en.cppreference.com/w/cpp/utility/optional
This data type wraps the inner type and provides methods to tell you if it has been set or not.
Note that you'll need a C++ 17 compiler.
Here's an example. You can see it's pretty easy to use and you don't need to create sentinel values (i.e. special values that are interpreted for the case of being not set).
#include <iostream>
#include <cstdlib>
#include <optional>
using namespace std;
int main()
{
optional<double> speed;
if (!speed)
{
cout << "speed not set" << endl;
}
speed = 0;
if (speed)
{
cout << "speed set to " << *speed << endl;
}
}
My knowledge in C++ is very limited, but judging from your description I believe that you are using primitive built-in type of C++ (int, double, bool, ...). If this is the case, then it is hard to know if your variable has been initialized since the primitive type all have their default value in case it is declared but not assigned a value.
One way I used to walk around this problem is that always init the variables with special default values. However, if the variables happen to be assigned values that match the default, that could be a problem.
However, I find it rarely happen because if you are using a library, then the class should have a method/ variable... to let you know the status of the current instance if necessary. Otherwise, the class should init default valid values, or you are using it the wrong way. If you are creating your own class, then it is easy to add a status variable to it, right?
Like I said, my knowledge is very limited, I could be wrong though.
I was coding with a beginner C++ group and we were creating a 'Car' class. Someone suggested 'tyre type' as a possible variable/attribute to the class as a boolean type. Another person then asked whether booleans should be directly answerable with a yes/no.
I was just wondering the same. How do you best manage a variable this and how do you later specify two options, such as winter/summer, for this variable?
Well, it depends.
Your goal is to write clear, readable, maintainable, and correct code. It's not so much that bool necessitates a yes vs. no answer as much as it is a question of whether or not using boolean (or any other type for that matter) helps you to meet these goals. If it makes your code clear, it's worth considering. If it makes things confusing, it's not a good idea.
For example, you may only have two types of tires, but consider a couple of things:
How do you know you won't add more later? You don't want to shoot yourself in the foot.
When writing / reading the code how do you remember that true is "summer" and false is "winter"? Will you have to maintain that info in your head / always look it up somewhere? Will it be easy to make a mistake? Will it confuse a reader who is unfamiliar with your code?
Think about those kinds of things. In your case, while using a boolean will certainly get the job done, I'd say it's a good use for an enum, even if you only have two values right now (or ever). E.g.:
enum TireType { WinterTire, SummerTire };
Now everything falls into place:
You can add new types in the future if you'd like, with no major issues.
A variable TireType t documents itself, we know just at a glance that t is a tire type.
There is much less of a chance of mistake when entering values: It'll be very hard to confuse WinterTire with SummerTire, whereas true and false discard all semantic meaning.
A boolean has two options, but those options are "true" or "false" (or, occasionally, "yes" and "no").
We do not generally represent other variables with two options as booleans.
If you have tyre types (of which there currently so happen to be two), I would suggest enums for this.
As always, there are exceptions. If your tyre types are "tyre with oil on it" and "tyre without oil on it", then you could use a boolean called tyreHasOilOnIt.
Really, it is up to you.
A boolean type is generally a value with precisely two values, one being truthy and the other falsy. This can to some degree be bent to other meanings. In your case when I saw discussion of tyre type I had no idea what the two values would mean untill reading the comments.
In my opinion when the value isn't self explanatory like this I would not use a boolean.
In your case, if the types of tyre are known at the time you write the program I would use an enum of some sort, and if they are not known just a plain string.
I would suggest don't use either enum or bool type for tyre type as a possible variable/attribute may change as you specified yes/no or Winter/Summer . Its better to use it as short int which values you can track or map with respect to yes,no,winter,summer . This will allow you to assign or change as per your need and class will never need a change.
Example :
Class car
{
// we will use tyre type to map enum
//type and other type if required
int tyreType;
};
enum tyre_type_t
{
//default value is considered 100
// since we can use previous
//value any other purpose.
WINTER = 100,
SUMMER
}
int main()
{
Car obj;
obj.tyreType = 1; // Yes
obj.tyreType = 0; // No
obj.tyreType = WINTER;
// Now we can assig enum.
// values //too.
return 0;
}
Happy Coding
Example :
Class car
{
// we will use tyre type to map enum
//type and other type if required
int tyreType;
};
enum tyre_type_t
{
//default value is considered 100
// since we can use previous
//value any other purpose.
WINTER = 100,
SUMMER
}
int main()
{
Car obj;
obj.tyreType = 1; // Yes
obj.tyreType = 0; // No
obj.tyreType = WINTER;
// Now we can assig enum.
// values //too.
return 0;
}
Happy Coding
I would like to know how.
I have looked at this topic, and I understand that "The choice of type is implementation-defined.", but I am curious to know how to get 1 instead of 4.
C++11 introduced a way to change the underlying type of an enum.
enum foo : char { ... };
enum class foo : char { ... };
Still, you're probably better off with using the default int in most cases.
On GCC, you can also use the 'packed' attribute to tell the compiler you care more about space than word alignment / access speed:
enum foo { ... } __attribute__((packed));
There are similar hints for other compilers too.
(This is useful when trying to avoid any C++11 features that aren't yet supported by your compiler or IDE.)
I have an Objective C selector which returns integers. I have a C++ instance method which expects an enum. How can I link them? I'm in an Objective C++ (.mm) class while I'm doing this.
I want to call this:
TKClass::foo(MyEnum enumVal) { ... }
With the return value of this:
- (int) intValue { ... }
Like this:
myCPPInstance->foo([myObjCInstance intValue]);
I've tried casting (foo((MyEnum) [myObjCInstance integerValue])) but it doesn't work. I definitely don't want my Objective C object to know anything about the enum; intValue needs to stay as an integer. Similarly, I don't really want to have the C++ method worry about integer inputs when it should be accepting enums.
I'm not much of a C++ programmer, so sorry if this is easy.
Thanks
EDIT: The enum is defined like this:
enum MyEnum {
Apples = 0,
Bananas = 1,
Chocolate = 2
};
It was a namespace issue. The cast should have been:
myCPPInstance->foo((myNamespace::MyEnum) [myObjCInstance intValue]);
Is it possible to get access to an individual member of a struct or class without knowing the names of its member variables?
I would like to do an "offsetof(struct, tyname)" without having the struct name or member variable name hard coded amoungst other things.
thanks.
Sure. If you have a struct and you know the offset and the type of the member variable, you can access it using pointers.
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
...
struct my_struct obj;
short member3 = *((short*)((char*)&obj + 5));
That'll get the value of member3, which is 5 bytes on from the start of obj on an x86 computer. However, you want to be careful. First of all, if the struct changes, your data will be garbage. We're casting all over the place, so you get no type safety, and the compiler won't warn you if something's awry. You'll also need to make sure the compiler's not packing the struct to align variables to word boundaries, or the offset will change.
This isn't a pleasant thing to do, and I'd avoid it if I were you, but yes, it can be done.
C and C++ are compiled languages without built-in "reflection" features. This means that regardless of what you do and how you do it, one way or another the path will always start from an explicit hard-coded value, be that a member name or an compile-time offset value. That means that if you want to select a struct member based on some run-time key, you have no other choice but to manually create a mapping of some kind that would map the key value to something that identifies a concrete struct member.
In C++ in order to identify a struct member at run-time you can use such feature as pointers-to-members. In C your only choice is to use an offset value.
Another issue is, of course, specifying the type of the members, if your members can have different types. But you provided no details about that, so I can't say whether you need to deal with it or not.
We had a similar problem some years ago: A huge struct of configuration information that we wanted to reflect on. So we wrote a Perl script to find the struct, parse its members, and output a C++ file that looked like:
struct ConfField
{ const char* name;
int type;
size_t offset;
};
ConfField confFields[] = {
{ "version", eUInt32, 0 },
{ "seqID", eUInt32, 4 },
{ "timestamp", eUInt64, 8 },
// ... lots more ...
{ 0, 0, 0 }
};
And we'd feed the script with the output from gcc -E.
Nowadays, I understand that gccxml can output an XML file representing any C++ source that gcc can compile, since it actually uses the g++ front end to do the parsing. So I'd recommend pairing it with an XML-parsing script (I'd use Python with the lxml library) to find out everything you ever wanted to know about your C++ source.
Somewhere in your code you need to reference the data member in the struct. However you can create a variable that is a pointer to a struct data member and from then on you no longer need to reference it by name.
struct foo
{
int member1;
int member2;
};
typedef int (foo::*intMemberOfFoo);
intMemberOfFoo getMember()
{
if (rand() > RAND_MAX / 2) return &foo::member1;
else return &foo::member2;
}
foo f;
void do_somthing()
{
intMemberOfFoo m = getMember();
f.*m = 0;
}
The technical answer is 'yes' because C++ is Turing-complete and you can do almost anything if you try hard enough. The more practical answer is probably 'no' since there is no safe and easy way of doing exactly what you want.
I agree with GMan. What exactly are you trying to do that makes you think you need this technique?
Well you will have to set up some stuff first, but it can be done. Expanding on Samir's response
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
you can create a table of offsets:
my_struct tmp;
int my_struct_offsets[4]={
0,
(char*)&(tmp.member2)-(char*)&(tmp.member1),
(char*)&(tmp.member3)-(char*)&(tmp.member1),
(char*)&(tmp.member4)-(char*)&(tmp.member1)
}
this will take into account different alignments on different systems