cppaddict said:
I recently started using typedefs and am curious if they are ever
considered evil.
They are good. Code should follow Don't Repeat Yourself. That rule's most
important for behavior (the stuff inside {} on methods). Consider types as
structure, which is less important to not duplicate, but every little bit
helps. For example:
typedef std::map<string, string> params_t;
bool
Product(params_t & testCase)
{
double num (strtod(testCase["Input1"].c_str(), NULL));
double den (strtod(testCase["Input2"].c_str(), NULL));
double quo (strtod(testCase["Product()" ].c_str(), NULL));
return num * den == quo;
}
I'm about to fold the lines that generally say double quo
(strtod(testCase["Product()" ].c_str(), NULL)); into a single reuseful
function. When I do, the typedef params_t will appear in its arguments. This
lets us upgrade params_t in only one place, and not write all the
std::map<etc etc> all over the place.
Further, the exact point where a template instantiates into a class tends to
conjoin that template with the types seen at the instantiation point.
Repeating std::map<etc etc> all over the place could generate subtle
differences between each instance, so instantiating with a typedef reduces
this risk, and instantiating in a header reduces it more. (It can't
eliminate it though, because users could #include their headers in any
order.)
In particular, I'm thinking of a situation where a typedef is used in
a file but defined in another, included file. Someone reading the
code might have to track down the original definition to make sense of
the code, and thus it reduces readability.
There are many ways to reduce readability by stretching out modules, so
their declarations are far away from their definitions, both physically and
cognitively far. To promote readability, write simple code in short methods,
and give everything the narrowest scope possible. If another module
somewhere needs a std::map<string, string>, I would _not_ put params_t into
a header that both its modules can see. I would write another typedef in
that module, with a different name.
Naming things after what their intent always helps readability. params_t
intends to store parameters to methods, as maps of strings. Another module
would name their typedef differently.
To help navigating even this short distance, with VC++, single-click on
params_t and tap <F12>.