I just saw this block of code on the Wikipedia article on conditional operators:
Vehicle new_vehicle = arg == \'B\' ? bus :
arg ==
A switch is both clearer and possibly much more efficient. If I saw code like this at a code review, I'd be worried. Also, this is "the conditional operator" - it is an instance (albeit currently the only one in C and C++) of a ternary operator.
Read the C++ section of the Wikipedia article a bit more carefully. It explicitly lists some situations where using the ?:
operator is the only option, and can't be replaced by if/else
or switch
.
On the other hand, I wouldn't use it only because it looks prettier.
A few people have already mentioned the possibility of using an std::map
or other associative array type to do the job. As long as you're only doing this is one place (or a few places), you might consider just using a normal array or vector instead:
Vehicle vehicles[CHAR_MAX];
// Initialization
std::fill_n(vehicles, CHAR_MAX, feet);
vehicles['A'] = airplane;
vehicles['B'] = bus;
vehicles['C'] = car;
vehicles['H'] = horse;
vehicles['T'] = train;
// Use
Vehicle new_vehicle = vehicles[arg];
Depending on how may tables you need/use (that store the same type of object), and the size of the contained objects (Vehicle in this case), this can be a perfectly reasonable alternative to an std::map
. If you're creating a lot of tables, or each object is really big, std::map
becomes a more reasonable alternative.
When you use an std::map
(or unordered_map
, etc.) you're using more code to save on data storage. This does the reverse -- but as long as Vehicle is small (say, 4 bytes), one table like the above will typically occupy something like half a kilobyte. It's hard to guess exactly how large the code for std::map
is going to be for a specific compiler, but it seems likely that it'll usually be larger than half a kilobyte, so if you're only creating one table like this, std::map
may be a net loss.
Of course, if you know that you're only dealing with letters as input, you could reduce the table size quite a bit:
template <class T>
class letter_table {
static const int range = 'Z' - 'A';
T table[range];
public:
// ...
T operator[](int index) {
index -= 'A';
assert(index<range);
return table[index];
}
};
In the example case, this would give a table around 100 bytes -- you can create a pretty fair number of 100-byte tables in the space std::map
will normally occupy.
I've never seen anything written like this before. While it is clever and well-formatted, this seems like the perfect opportunity to use a dictionary/hashtable (assuming Vehicle
is an enumeration, which is unclear).
I like it. It is similar to an if-else-if ladder, only more concise.
I have used this type of construction many times. As long as it's formatted nicely (i.e. not all on one line, making it unreadable), I don't see a problem with it.