Is naming variables after their type a bad practice?

Viewed 8199

I'm programming C++ using the underscore naming style (as opposed to camel case) which is also used by the STL and boost. However, since both types and variables/functions are named all lower case, a member variable declaration as follows will lead to compiler errors (or at least trouble):

position position;

A member variable named position which is of type position. I don't know how else to name it: It's generally a position, but it is also the position of the object. In camel case, this would be fine with the compiler:

Position position;

But in C++ it causes problems. I don't want to switch to camel case, use Hungarian notation or add a trailing underscore because of that, so I'm wondering: Is it a good practice to name a member like a type anyways?

In C, it is pretty common to use cryptic one-letter variables for this:

int i;

But I find that a bit, well, cryptic:

position p;

Are there any rules of thumb for variable naming I can use to avoid this?

There are more examples in my code if you need something to work on:

mouse_over(entity entity) // Returns true if the mouse is over the entity

manager &manager; // A reference to the framework's manager

audio audio; // The audio subsystem

Edit:

I was curious to see if Bjarne Stroustrup himself has something to say on this issue. Apparently, he hasn't, but he suggests coding conventions that would work around my compiler problems:

For example, capitalize nonstandard library user-defined types and start nontypes with a lowercase letter

That'd be consistent with STL and boost, so I might use that. However, most of you agree that this naming should be avoided whether it compiles or not. So does Stroustrup:

it is unwise to choose names that differ only by capitalization.

11 Answers

No, I do this on occasions and it does not cause problems in the Microsoft world. For example,

class compiler
{
    symbol_table symbol_table;
};

has never caused any confusion. By the way, I called my cat 'cat' and that hasn't caused confusion either.

The biggest problem with this naming convention imo is that it's unclear to the programmer whether an expression refers to a type or an object. A way to eliminate such ambiguity is by wrapping your code inside a namespace (as it should) and using explicit qualifications, even on internal usage:

namespace my_ns {

struct audio { ... };
struct string { ... };

// Internal function whose logic doesn't require explicit qualifications.
void do_something()
{
    // Use explicit qualification nevertheless.
    my_ns::audio audio;
    audio.play("impenetrable.sd2"); // okay

    my_ns::string string;
    string.size();          // okay
    // string{}.size();     // oof, tryna re-instantiate object? compilation error
    my_ns::string{}.size(); // okay, size of just created temporary string
}

}

This is much like the way you use standard types such as std::string. Since all user-defined types will be qualified with their namespace, there'll be no ambiguity between types and objects. The downside of this is, of course, more verbosity:

namespace my_ns {

struct audio {
    // Using explicit qualification; pretty verbose.
    void play(my_ns::string a1, my_ns::string a2, my_ns::string a3);

    // Without explicit qualification; saves 21 characters.
    void play(string a1, string a2, string a3);
};

}
Related