Namespaces, Enums, Scope, and Conversions
Variables and Data Types

1.7 Namespaces, Enums, Scope, and Conversions

These language tools appear in nearly every real C++ codebase. Learn them before pointers and classes so the code you read has clear names, states, and ownership boundaries.

Namespaces prevent name collisions

A namespace groups names. The standard library uses std, which is why course examples write std::vector and std::cout. Avoid using namespace std; in headers and production code: it imports many unrelated names and can make an innocent-looking identifier ambiguous.

namespace telemetry {

int parsePort(const char* text) {
    return 9000;
}

} // namespace telemetry

int main() {
    return telemetry::parsePort("9000") == 9000 ? 0 : 1;
}
Keep application names in a namespace.

Use enum class for a closed set of states

An enum class creates scoped enumerators and does not silently convert to an integer. Prefer it over unscoped enum for domain states, protocol tags, and options.

enum class ConnectionState {
    connecting,
    ready,
    closed,
};

bool canSend(ConnectionState state) {
    return state == ConnectionState::ready;
}
A scoped enum makes invalid states harder to express.

Scope controls lifetime

A block delimited by { and } is a scope. Automatic objects are destroyed in reverse construction order when execution leaves that scope. This language rule, not a guessed stack address, is the basis for RAII in later lessons.

int main() {
    int result{0};
    {
        const int temporary{42};
        result = temporary;
    } // temporary is no longer in scope or alive
    return result == 42 ? 0 : 1;
}
A local object's lifetime ends at the closing brace.

Let the initializer guide auto, but preserve intent

auto asks the compiler to deduce a type from an initializer. It is useful when the initializer makes the type obvious or when the explicit type is noisy. Be deliberate about references and constness: auto drops top-level const and references, while const auto& is a read-only alias.

For conversions, prefer an explicit cast only when you can state why it is safe. static_cast expresses a checked-by-you numeric or hierarchy conversion; never use it to hide a narrowing or lifetime bug. Brace initialization rejects many narrowing conversions, which is why it is a good default.

Practice: define an enum class LogLevel, write a switch that handles every value, and explain why a const auto& alias must not outlive the object it observes.

Finished reading this lesson?