Is naming variables after their type a bad practice?
The local meaning is rarely a good unique global description of the type:
cartesian_point_2d position; // rectangular, not polar coordinates
mouse_over(ui_entity entity); // not a business layer entity
xyz_manager& manager; // what's a manager without something to manage?
audio_system audio;
Naming variables after their type specifically is indeed a bad practice. The code is supposed to be as type-independent as possible. That implies that any references to actual types should be restricted to declarations (again, as much as possible). Trying to embed type information into variable name would violate that principle. Don't do it.
What one might want to embed into variable name is the variable's semantical meaning. Like "width", "length", "index", "coordinate", "rectangle", "color", "string", "converter" and so on. Unfortunately, many people, when they see it, incorrectly assume that these portions of the names are intended to describe the type of the variable. This misunderstanding often makes them to engage into that bad practice (of naming variables after their types) later in their code.
A classic well-known example of such misunderstanding is so called Hungarian notation. Hungarian notation implies prefixing variable names with special unified prefixes that describe the semantic of the variable. In this original form Hungarian notation is an extremely useful good naming convention. However, in many practical cases it gets distorted into something completely different: prefixing the variable names with something that describes their type. The latter is certainly not a good idea.
Giving a variable the same name as its type is almost always a bad idea, because it makes it very difficult to tell what code refers to the type and what code refers to the variable. For example, consider the following class:
struct position
{
void operator()() { }
};
// later on, somewhere:
position position;
Now, if we see a line of code that uses:
position()
we can't readily tell whether that constructs a position
object or calls position::operator()()
. We have to go back and see whether there is an object named position
currently in scope.
Naming conventions are a very touchy, subjective, and argumentative thing. I would just recommend picking one that distinguishes types from variables in some way. Personally, I choose to capitalize my types and leave my variables as starting with a lowercase letter.
It doesn't really matter how you distinguish them (your suggestions of using capitalization or a trailing underscore are both common), just so long as your usage is consistent.