Here's a version that suffers from neither the problem clang's reporting or the one you're guarding against:
void myFunction(testingMask theMask) {
assert(theMask == MaskValueUno || theMask == MaskValueDos);
switch (theMask) {
case MaskValueUno: {}// deal with it
case MaskValueDos: {}// deal with it
}
}
Killian has explained already why clang emits the warning: if you extended the enum, you'd fall into the default case which probably isn't what you want. The correct thing to do is to remove the default case and get warnings for unhandled conditions.
Now you're concerned that someone could call your function with a value that's outside the enumeration. That sounds like failing to meet the function's prerequisite: it's documented to expect a value from the testingMask
enumeration but the programmer has passed something else. So make that a programmer error using assert()
(or NSCAssert()
as you said you're using Objective-C). Make your program crash with a message explaining that the programmer is doing it wrong, if the programmer does it wrong.
This is a great fit for a map (2nd or 3rd proposed solution). I've used it dozens of times, and it's simple and effective. I don't really distinguish between these solutions; the important point is that there is a map with function names as the keys.
The major advantage of the map approach, in my opinion, is that the table is data. This means that it can be passed around, augmented, or otherwise modified at runtime; it's also easy to code additional functions which interpret the map in new, exciting ways. This wouldn't be possible with the case/switch solution.
I haven't really experienced the cons that you mention, but I would like to mention an additional drawback: dispatching is easy if only the string name matters, but if you need to take additional information into account in order to decide which function to execute, it's a lot less clean.
Perhaps I've just never run into a hard enough problem, but I see little value in both the command pattern and encoding the dispatch as a class hierarchy, as others have mentioned. The core of the problem is mapping requests to functions; a map is simple, obvious, and easy to test. A class hierarchy requires more code and design, increases the coupling between that code, and may force you to make more decisions upfront that you will later be likely to need to change. I don't think the command pattern applies at all.
Best Answer
Several options:
the naive method would be an if else cascade (slow)
the compiler can sort the cases behind the scene and then do a binary search (good for disjoint cases)
a jump table; only good for sequential cases but very fast.
For string-based switches there is the option of the prefix Trie, a sorted table that can be binary searched or the strings are hashed and used for the cases of a switch against the hash of the input string with a double check in each case.