We have enum type definition
enum TokenKind
{
// changed in order to reflect the priority
tkNamespace = 0x0001,
tkClass = 0x0002,
tkEnum = 0x0004,
tkTypedef = 0x0008, // typedefs are stored as classes inheriting from the typedef'd type (taking advantage of existing inheritance code)
tkConstructor = 0x0010,
tkDestructor = 0x0020,
tkFunction = 0x0040,
tkVariable = 0x0080,
tkEnumerator = 0x0100,
tkPreprocessor = 0x0200,
tkMacro = 0x0400,
// convenient masks
tkAnyContainer = tkClass | tkNamespace | tkTypedef,
tkAnyFunction = tkFunction | tkConstructor | tkDestructor,
// undefined or just "all"
tkUndefined = 0xFFFF
};
But in some cases, we need a mask, like:
Token* TokenExists(const wxString& name, const Token* parent = 0, short int kindMask = 0xFFFF);
Note, here the mask type is: short int, TokenKind is not allowed here, because if you put here, then some code like:
TokenExists(, , tkTypedef | tkClass);
will compiler error, like: error: invalid conversion from 'int' to enum type TokenKind.
There are many discussion:
on enum and bitwise operation (http://stackoverflow.com/questions/7840714/on-enum-and-bitwise-operation)
How to use enums as flags in C++? (http://stackoverflow.com/questions/1448396/how-to-use-enums-as-flags-in-c)
and more.
So, what's your opinion on this, I think using a TokenKind for the function argument is better.
Do we use:
TokenExists(, , static_cast<TokenKind>(tkTypedef | tkClass));
Or, we can define some bitwise operator like in this post http://stackoverflow.com/a/1448478/154911
enum AnimalFlags
{
HasClaws = 1,
CanFly =2,
EatsFish = 4,
Endangered = 8
};
inline AnimalFlags operator|(AnimalFlags a, AnimalFlags b)
{return static_cast<AnimalFlags>(static_cast<int>(a) | static_cast<int>(b));}
...
I see some code in CC use type conversion, like:
else if (command == cmdSearchAll)
tree->FindMatches(args, result, true, false, TokenKind(kindToSearch));
else
tree->FindMatches(args, result, true, false, TokenKind(tkAnyContainer|tkEnum));
The function prototype is:
size_t FindMatches(const wxString& query, TokenIdxSet& result, bool caseSensitive, bool is_prefix, TokenKind kindMask = tkUndefined);
It is strictly legal for an enumeration value to be a value that is not part of the enumeration definition, as long as it fits the storage size.
Can you quote the standard?
@ollydbg:
I don't see where the problem with using short int parameter is coming from?
This compiles without errors on GCC 4.4
enum TokenKind
{
// changed in order to reflect the priority
tkNamespace = 0x0001,
tkClass = 0x0002,
tkEnum = 0x0004,
tkTypedef = 0x0008, // typedefs are stored as classes inheriting from the typedef'd type (taking advantage of existing inheritance code)
tkConstructor = 0x0010,
tkDestructor = 0x0020,
tkFunction = 0x0040,
tkVariable = 0x0080,
tkEnumerator = 0x0100,
tkPreprocessor = 0x0200,
tkMacro = 0x0400,
// convenient masks
tkAnyContainer = tkClass | tkNamespace | tkTypedef,
tkAnyFunction = tkFunction | tkConstructor | tkDestructor,
// undefined or just "all"
tkUndefined = 0xFFFF
};
void func(int a, short int b=tkUndefined) {
int c;
c=a+b;
}
int main() {
func(1, tkTypedef | tkClass);
return 0;
}
Hm, if I understand §7.2 par 8 correctly, then you're wrong, because this paragraph explicitly forbids int to enum conversions.
Here is the example taken from the standard:
enum color { red, yellow, green=20, blue };
color col=red; // ok
color c=1; // error - type mismatch, no conversion from int to color
int i=yellow; //ok, yellow converted to integral value 1